Summary of new features of C + + standard 11-14

  • 1. Evolution, environment and resources
    • Version: c++98 (1.0), c++04, c++11 (2.0), c++14
  • 2. Variable template (key and difficult)
    • ... is a pack age, which represents any number and type of parameters
    • Template parameters Pack: template parameters pack
    • Function parameter types Pack: function parameter types pack
    • Function parameter Pack: function parameter pack
    • Template has the concept of specialization. In overloading, the function that is more special will be called.
    • However, if the number of parameter types is uncertain but the parameter types are the same, use initialize_list is more convenient and fast, but {} needs to be added outside the parameters for modification. Using variable templates requires recursion, and the efficiency will be different. ( C + + variable templates _A_Bo's blog - CSDN blog)
    • code:
      • #include<iostream>
        using namespace std;
        namespace variadic{
        	void print(){
        	}
        	
        	template <typename T, typename... Types>
        	void print(const T& firstArg, const Types&... args){
        		cout << sizeof...(args) << " " << firstArg << endl;
        		print(args...);
        	}
        	template<typename... Values> class tuple;
        	template<> class tuple<> {};
        	template<typename Head, typename... Tail>
        	class tuple<Head, Tail...>: private tuple<Tail...>{
        		typedef tuple<Tail...> inherited;
        		public:
        			tuple() {}
        			tuple(Head v, Tail... vtail): m_head(v), inherited(vtail...) {}
        			
        			Head head() {return m_head;}
        			inherited& tail() { return *this; }
        		protected:
        			Head m_head;
        	};
        	
        	
        }
        using namespace variadic;  // If this line is not added, the compilation will not pass 
        int main(){
        	int a = 1;
        	char c = 'T';
        	int b[10] = {0};
        	string s("abs");
        //	Cout < < B < < endl; / / the address is printed 
        //	s = "dsd"; / / can be compiled
        	print(a, c, b, s); 
        
        //	tuple<int, float, string> t(41, 6.3, "nico");
        //	cout << t.head() << endl;
        //	cout << t.tail().head() << endl;
        	return 0;
        }

  • 3. Spaces in Template Expression,nullptr,auto
    • Spaces in Template Expression
      • Vector < vector < int > > V; can be written as vector < vector < int > > V; (the space in the middle can not be written)
    • nullptr
      • C++11 At the beginning, the constant value of null pointer is defined as nullptr
    • auto
      • Auto can automatically deduce the type of variable. When the type is long or complex expression lambda, auto can be used instead.
  • 4. Unifrom initialization consistency initialization
    • Consistency initialization, as the name suggests, means that the old version of C + + initialization is inconsistent, while the new version is consistent. Indeed, the initialization of the old version of C + + may occur in parentheses, curly braces or assignment symbols. Therefore, C++11 introduces consistency initialization, all of which are initialized with curly braces( 4.Uniform Initialization, Initializer list _baidu _17611285blog - CSDN blog)
    • It should be noted that the elements in the initializer_list object are always constant values, and we cannot change the values of the elements in the initializer_list object. In addition, copying or assigning an initializer_list object will not copy the elements in the list, but is actually just a reference. The essence of the original column table and the copy share elements is that it is a shallow copy, and the two are only one at the bottom The pointer points to an address at the same time.
    • Now with the initializer_list < >, all containers accept any number of values of the specified type for construction or assignment (the types should be consistent, {} will not be type converted).
    • code:
      • vector<int> v {1, 2, 3, 4};
  • 5. Initialzer_list
    • std::initializer_list has three member interfaces: size(), begin(), end();
  • 6. Explicit for ctors taking more than one argument
    • explicit is added, and the constructor must be explicitly called. Implicit call to the constructor is not allowed.
    • code:
      • #include<iostream>
        struct Complex{
        	double _real;
        	double _i;
        //	Explicit / / explicit is added. The constructor must be explicitly called 
        	Complex(double real, double i = 0) : _real(real), _i(i) {}
        	Complex operator + (const Complex &c){
        		return Complex(c._real + _real, c._i + _i);
        	}
        	~Complex() = default;
        };
        int main() {
        	Complex c1(4, 2);
        	Complex c2 = c1 + 5; // The compiler implicitly calls the constructor to construct a Complex(5)
        	return 0;
        }
        

  • 7. Range - based for statement
    • code:
      • vector<int> v {1,2, 3,4};
      • for (auto a : v)
        • cout << a << endl;
  • 8. =default. =delete(https://blog.csdn.net/baidu_17611285/article/details/80505902)
    • Big Five: default constructor, default copy constructor, default assignment constructor, move constructor, move assignment constructor
    • Default is the big five specifically used for the above. It means that when we have defined special construction, copy construction, assignment construction, mobile construction and other functions, the compiler will not automatically add big five. However, if you still want to use these default functions, you can add = default to implement them, as shown in the figure below. And "= delete" It means that we don't want this function. If we call a function with "= delete", the compiler will report an error. In addition, "= delete" can be added to any function, not limited to class member functions. Default can also be used for destructors, but it is rarely used.
    • =default (can also be used on destructors)
      • In the standard library, default is a function for big five.
    • =delete
    • As long as a class has pointer members, it almost concludes that we need to write those big three (constructs, copy constructs, assignment constructs, C++11 is big five) On the contrary, if there is no pointer member, there is almost no need to implement big three by yourself. Generally, the compiler default is enough. Because the default copy of the compiler is a shallow copy, and those with pointers only copy the pointer itself. Generally, we need a deep copy, that is, the memory referred to by the pointer needs to be reallocated and copied.
    • code:
    •  
      #include<iostream>
      using namespace std;
      class Zoo{
      	private:
      		int d1, d2;
      	public:
      		Zoo(int i1, int i2):d1(i1), d2(i2) {}
      		// Because the constructor is written, the system will not automatically generate the constructor.
      		// Therefore, if you do not write the following line, Zoo z1; will report an error. 
      		Zoo() = default;   
      		Zoo(const Zoo&) = delete;
      		Zoo(Zoo &&) = default;
      		Zoo& operator = (const Zoo&) = default;
      		Zoo& operator = (const Zoo&&) = delete;
      		virtual ~Zoo() {}
      }; 
      
      int main() {
      	Zoo z1;
      //	Zoo z2(z1); / / because Zoo (const Zoo &) = delete; is used, an error is reported in this line 
      	return 0;
      }

  • 9. Alias Template( 8.Alias Template _baidu _17611285blog - CSDN blog _aliastemplate)
    • using is similar to typedef in C + +, but the new mechanism of C++11 is not only to write fewer words by setting the template alias, but also cannot be replaced by typedef or #define
    • code:
    • #include<iostream>
      #include<vector>
      using namespace std;
      //  The template should be placed outside the function 
      // Use typedef syntax to copy, etc 
      template<typename T>
      using Vec = vector<T, allocator<T>>;
      
      template <typename T, template <class> class Container>
      class XCLs {
      	private:
      		Container<T> c;
      	public:
      		XCLs() {
      			for(long i = 0; i < 10; i++)
      				c.insert(c.end(), T()); 
      				
      //			output_static_data(T());
      			Container<T> c1(c);
      			// std::move is to transfer the state or ownership of an object from one object to another. It is just a transfer. There is no memory relocation or memory copy, so it can improve utilization efficiency and performance.
      			Container<T> c2(std::move(c));
      			c1.swap(c2);
      		}
      };
      int main() {
      	XCLs<int, Vec> c1;
      	return 0;
      }

  • 10.Template template parameter
  • 11. Type Alias, noexception, override, final(Blog of Type Alias, noexcept, override, final_u013635579 - C SDN blog)
    • Type Alias
      • code:
        • class Base {};
        • using A = Base;
    • noexception
      • noexcept to specify that a function will not throw an exception
    • override
      • The override keyword provided in C++11 can solve this problem. It marks the virtual function in the derived class. If the virtual function in the base class is not overwritten, the compiler will report an error
    • final
      • final adds two new functions: (1) prohibit base classes from being inherited, (2) prohibit virtual functions from being rewritten;
  • 12. decltype
    • Decltype (expression) returns the type of the expression (which can make the function).
    • dectype does not execute the expression, just pushes out the type, and auto executes.
  • 13. lambdas(Lambda expression of C + + - paradise at the end of the season - blog Park)
    • The lamdba function is an inline function.
    • [function object parameter] (operator overloaded function parameter) mutable or exception declaration - > return value type {function body}
    • Lambda expressions in C++ 11 are used to define and create anonymous function objects to simplify programming.
    • Empty. There are no function object arguments.
    • =All visible local variables within the scope of Lambda (including this of Lambda's class) can be used in the phase function body, and it is the value transfer method (phase function)
    • When the compiler automatically passes us all local variables by value).
    • &All visible local variables within the scope of Lambda (including this of Lambda's class) can be used in the function body, and are passed by reference
    • (so the compiler automatically passes us all local variables by reference).
    • this. In the function body, you can use the member variables in the class of Lambda.
    • a. Pass a by value. When passing by value, the copy of a passed in cannot be modified in the function body, because the function is const by default
    • To modify the passed in copy, you can add the mutable modifier.
    • &a. Pass a by reference.
    • a,&b. Pass a by value and B by reference.
    • =,&a,&b. Except that a and B are passed by reference, other parameters are passed by value.
    • &,a,b. Except that a and B are passed by value, other parameters are passed by reference.
  • 14. Rvalue reference and Move Semantics
    • lvalue (locator value) represents an object that occupies a certain location in memory (in other words, it has an address).
    • Rvalue is defined by exclusivity. Each expression is either lvalue or rvalue. Therefore, from the above definition of lvalue, rvalue is an expression that does not occupy a certain position in memory.
    • give an example: Understand left and right values in C and C + +_ xuwqiang1994 blog - CSDN blog
      • Neither the constant 4 nor the expression var+1 is lvalue (they are rvalue). They are not lvalues because they are all temporary results of expressions and have no definite memory space (in other words, they just reside in temporary registers for the period of calculation). So assigning them has no meaning - there is no place to assign them.
      • Foo returns a temporary rvalue. Trying to assign a value to it, foo()=2, is an error; The compiler expects to see an lvalue in the left part of the assignment operator.
      • Not all assignments to function call results are invalid. For example, the reference of C + + makes this possible:
      • const int a = 10; //‘ A 'is an lvalue
      • a = 10; // But it cannot be assigned
      • [...] an lvalue has no array type, no incomplete type, no const modified type, and if it is a structure or union, there is no const modified member (containing, recursive containing, collection of any member elements).
      • A non function, non array type lvalue t can be converted to an lvalue. [...] If t is a non class type, the R-value type converted is a non CV modified version of T. Otherwise, the right value type is t.
      • &&Syntax is a new R-value reference. Indeed, it's the same name - give us a reference to the right value that will be destructed after the call. We can use the fact that we just "steal" the internal r-values - we don't need them at all! Output is:
    • code:
    • #include<iostream>
      using namespace std;
      
      class Intvec
      {
      public:
          explicit Intvec(size_t num = 0)
              : m_size(num), m_data(new int[m_size])
          {
              log("constructor");
          }
      
          ~Intvec()
          {
              log("destructor");
              if (m_data) {
                  delete[] m_data;
                  m_data = 0;
              }
          }
      
          Intvec(const Intvec& other)
              : m_size(other.m_size), m_data(new int[m_size])
          {
              log("copy constructor");
              for (size_t i = 0; i < m_size; ++i)
                  m_data[i] = other.m_data[i];
          }
      
      //    Intvec & operator = (const intvec & & other) / / execute v2 = v1; Will report an error 
          Intvec& operator=(const Intvec& other)
          {
              log("copy assignment operator");
              Intvec tmp(other);  // After the function is executed, tmp will be released 
              // The content in other is still there
              std::swap(m_size, tmp.m_size);   //Since other is a constant type, std::swap(m_size, other.m_size) cannot be called;
              std::swap(m_data, tmp.m_data);
              return *this;
          }
          
          Intvec& operator=(Intvec&& other) // Understand & & as stealing 
      	{
      	    log("move assignment operator");
      	    std::swap(m_size, other.m_size);
      	    std::swap(m_data, other.m_data);
      	    return *this;
      	}
      private:
          void log(const char* msg)
          {
              cout << "[" << this << "] " << msg << "\n";
          }
      
          size_t m_size;
          int* m_data;
      };
      int main() {
      	Intvec v1(20);
      	Intvec v2;
      	
      	cout << "assigning lvalue...\n";
      //	v2 = v1;
      	//  Intvec(33) constructs a temporary object. After executing the following statement, it will be released. 
      	// Intvec & operator = (const intvec & other), if there is const type in it, otherwise if the = overloaded function is not written, the system will say that the = overloaded function cannot be found 
      	//	Or write intvec & operator = (intvec & & other)  
      	v2 = Intvec(33);    //The system calls intvec & operator = (intvec & & other)  
      	
      	cout << "ended assigning lvalue...\n";
      	return 0;
      }

  • 15. Perfect Forwarding
    • As the name suggests, perfect forwarding is to forward the parameters to the next function without changing the attributes. Once the parameters of an ordinary function are named, they are always lvalue. If rvalue is forwarded to the parameters on the next function, it is rvalue (which will not generate too much memory). This is the purpose of perfect forwarding.
  • 16. Move-aware class
  • 17. Vector
    • vector can only contain objects, not reference types.
    • Reference is not an object.
  • 18. Hashtable, Hast funciton
    • Hastfunciton (the system will have a function to calculate hashcode)
  • 19. Tuple
    • Metaprogramming operates on types.
    • See 2. Variable template code.

Keywords: C++

Added by rweston002 on Thu, 30 Sep 2021 00:44:37 +0300