C ++ 11 deep learning

Source: Internet
Author: User

C ++ 11 deep learning

Delegate constructor

Before C ++ 11 is introduced, if a class has multiple overloaded constructors and these constructors have some common initialization logic, you usually need to write another initialization function with parameters, and then call this initialization function in these constructors. In C ++ 11, you don't have to worry about it any more. We can implement a most basic constructor. All other constructor calls this constructor. The sample code is as follows:

 

 

 

 

1 class CPerson

2 {

3 public:

4 CPerson (): CPerson (0,) {NULL ;}

5 CPerson (int nAge): CPerson (nAge,) {NULL ;}

6 CPerson (int nAge, const string & strName)

7 {

8 stringstream ss;

9 ss <strName <is <nAge <years old .;

10 m_strInfo = ss. str ();

11}

12

13 private:

14 string m_strInfo;

15 };

 

 

Unified initialization syntax

There are various initialization syntaxes before C ++ 11 is introduced. In C ++ 11, you can still use these initialization syntaxes, but you can also choose to use the new unified initialization syntax. The unified initialization syntax is represented by a pair of braces {}. The {} initialization syntax can effectively avoid narrow conversions. The sample code is as follows:

 

 

 

 

1 int a {5 };

2 char c {'X '};

3 int p [5] = {1, 2, 3, 4, 5 };

4 vector VctTemp {1, 2, 3 };

5 CPerson person {10, Mike };

6 int B = 5.3; // B is assigned to 5, resulting in a narrow conversion.

7 int d {5.3}; // a compilation error is prompted to avoid narrow conversions.

 

 

Syntax dessert 4: nullptr

Nullptr is a newly added keyword in C ++ 11, used to identify a null pointer. After nullptr is introduced, the ambiguity of some function overloading can be solved. The sample code is as follows:

 

1 void F (int)

2 {

3 cout <a <endl;

4}

5

6 void F (char * p)

7 {

8 assert (p! = NULL );

9

10 cout <p <endl;

11}

12

13 int main (int argc, _ TCHAR * argv [])

14 {

15 int * p = nullptr;

16 int * q = NULL;

17 bool bEqual = (p = q); // The two pointer values are equal, and bEqual is true.

18 int a = nullptr; // compilation failed, nullptr is not converted to int

19

20 F (0); // The compilation fails in C ++ 98, which has ambiguity. In C ++ 11, F (int) is called)

21 F (nullptr); // call F (char *)

22

23 getchar ();

24 return 0;

25}

 

 

Member variable Initialization

Similar to Java and C #, You can initialize member variables locally. The sample code is as follows:

 

 

1 class CPerson

2 {

3 private:

4 int m_nAge = 10;

5 string m_strName = Mike;

6 };

 

 

Default function or disabled Function

When we define our own constructor with parameters, the compiler will no longer generate default constructor. If we want to use the default constructor at this time, you must explicitly declare and define constructors without parameters. In C ++ 11, we can use the default keyword to indicate that we want to use the default constructor. Similarly, when we do not want to use the constructors or value assignment functions automatically generated by the compiler, we generally need to declare them as protected or private. In C ++ 11, we can use the delete keyword to indicate that we do not want the compiler to generate the default constructor or value assignment function. The sample code is as follows:

 

 

1 class CPerson

2 {

3 public:

4 CPerson () = default;

5 CPerson (const CPerson & person) = delete;

6 };

 

 

Static_assert

Static assertions static_assert consist of a constant expression and a string. During compilation, the value of the constant expression will be calculated. If it is false, the string will be output as an error message. The sample code is as follows:

 

 

1 char a = 10;

2 static_assert (sizeof (a) = 4, a is not an integer .);

 

 

Double brackets on the right of the template

In C ++ 98, vector > VctTemp is an invalid expression. The Compiler considers> on the right as a shift operator and must be modified to vector. > VctTemp: Add a space between the two on the right. In C ++ 11, this is no longer a problem. the compiler will be able to identify that the double parentheses on the right are the knot of the two template parameter lists.

-

 

Inherited Constructor

When a function in a derived class hides a function of the same name in the Base class, if you want to export the function of the same name in the Base class in the derived class, you can use using Base :: func introduces the function of the same name in the base class to the scope of the derived class. This method is only valid for common member functions and cannot be used for constructors. In C ++ 11, if the derived class thinks that the Base class constructor is sufficient, you can also use using Base :: base to introduce the Base class constructor to the scope of the derived class. Note that the member variables in the derived class are not initialized at this time, so these member variables should be initialized locally. The sample code is as follows:

 

 

 

 

1 class CBase

2 {

3 };

4

5 class CDerived: public CBase

6 {

7 public:

8 using CBase: CBase;

9 CDerived (int nData): m_nData (nData) {NULL ;}

10

11 private:

12 int m_nData = 10;

13 };

 

 

Initialization list

Before C ++ 11 is introduced, only Arrays can use the initialization list. In C ++ 11, various containers, such as vector and list, and strings can all use the initialization list. The class corresponding to the initialization list is initializer_list, vector, list and other containers, and the reason why string can use the initialization list is that they reload the constructor whose parameter type is initializer_list (called the initialization list constructor) and the value assignment function (called the initialization list assignment function ). The following are examples of using the initialization list.

 

 

 

 

1 void Print (const initializer_list & IlData)

2 {

3 for (auto a: ilData)

4 {

5 cout <a <endl;

6}

7}

8

9 int main (int argc, _ TCHAR * argv [])

10 {

11 vector VctNum = {1, 2, 3, 4, 5 };

12 map MapID2Name = {92001, Jack}, {92002, Mike }};

13 string strText {hello world };

14 Print ({});

15 Print ({1, 2 });

16 Print ({1, 2, 3, 4, 5 });

17

18 getchar ();

19 return 0;

20}

 

 

 

Non-member begin and end

In C ++ 03, the standard container provides the begin and end member functions, but for common arrays, you can only use different writing methods. For example:

 

 

1 vector V;

2 int a [100];

3 sort (v. begin (), v. end ());

4 sort (a, a + sizeof (a)/sizeof (a [0]);

To unify the syntax, C ++ 11 provides non-member begin and end functions. The usage is as follows:

 

 

1 sort (begin (v), end (v ));

2 sort (begin (a), end ());

 

 

Explicit virtual function overload

 

Before C ++ 11 is introduced, the virtual functions in the base class and the derived class are prone to incorrect usage. For example:

 

A. a virtual function is added to the base class, but the virtual function is the same as an existing common function in the derived class.

 

B. A common function is added to a derived class, but the function is the same as an existing virtual function in the base class.

 

To avoid these problems, override can be used in C ++ 11 to explicitly indicate that virtual function Overloading is required. For example:

 

 

1 class Base

2 {

3 virtual void some_func (float );

4 };

5

6 class Derived: public Base

7 {

8 virtual void some_func (int) override; // compilation Error

9 virtual void some_func (float) override; // correct

10 };

 

 

 

The final indicator is introduced in C ++ 11 to prevent class or interface inheritance. For example:

 

 

 

1 class Base1 final {};

2 class Derived1: public Base1 {}; // compilation error will be generated

3 class Base2

4 {

5 virtual void f () final;

6 };

7 class Derived2: public Base2

8 {

9 void f (); // compilation Error

10 };

 

 

In C ++ 03, you can use typedef to specify a new type name for the template class, but you cannot specify an alias for the class template. For example:

 

1 template <typename first, typename second, int third>

2 class SomeType; template <typename second>

3 typedef SomeType TypedefName; // It is invalid in C ++ 03

 

 

 

Unrestricted union

 

In C ++ 03, not any data type can be used as a member of union. For example, a type with a non-trivial constructor cannot be a member of union. In C ++ 11, all restrictions on the use of union are removed, except that its members still cannot be reference types.

 

 

 

 

1 struct point

2 {

3 point (){}

4 point (int x, int y): m_x (x), m_y (y ){}

5 int m_x, m_y;

6 };

7 union

8 {

9 int z;

10 double w;

11 point p; // invalid in C ++ 03; valid in C ++ 11

12 };

 

In C ++ 11, the sizeof operator is allowed to act on data members of the type without explicit objects. In C ++ 03, this is not allowed and may cause compilation errors. For example:

1 struct SomeType {OtherType member ;};

2 sizeof (SomeType: member); // invalid in C ++ 03; valid in C ++ 11

 

New Algorithm

 

Some useful algorithms are added in C ++ 11. For example, all_of, any_of, none_of, copy_n, copy_if, and iota. The reference code is as follows:

 

 

1 int a [5] = {-2,-1, 0, 1, 2 };

2 auto funIsPositive = [] (int v) {return v> 0 ;};

3 bool bRet = all_of (a, a + 5, funIsPositive); // false

4 bRet = any_of (a, a + 5, funIsPositive); // true

5 bRet = none_of (a, a + 5, funIsPositive); // false

6 int B [5] = {0 };

7 copy_n (a, 5, B); // copy the Five Elements starting with a to B.

8 copy_if (a, a + 5, B, funIsPositive); // copy the numbers 1 and 2 to B.

9 iota (a, a + 5, 10); // Add 10 to each element in

 

 

Generalized constant expression

 

C ++ 03 already has the concept of constant expression, such as 3 + 5 and 6*7. Constant expression is an opportunity for the compiler to optimize. The Compiler often runs them during compilation and stores values in the program. Similarly, in many cases, the C ++ specification requires constant representations. For example, the array size and enumeration value.

 

However, the constant expression always ends when a function call is encountered. For example:

1 int GetFive () {return 5 ;}

2 int some_value [GetFive () + 5]; // invalid

 

 

The keyword constexpr introduced in C ++ 11 allows you to ensure that the function is a constant during compilation. For example:

1 constexpr int GetFive () {return 5 ;}

2 int some_value [GetFive () + 5];

 

 

 

 

 

A very important and difficult to understand new feature introduced in C ++ 11 is the Perfect Forwarding (Perfect Forwarding ). Perfect forwarding has two keywords: "forwarding" and "perfect ".

Let's take a look at the first keyword "Forward". What does "Forward" mean in C ++? Forwarding is usually used in template programming. Assume that there is a function F (a1, a2 ,..., an), if another function G (a1, a2 ,..., an), calling G is equivalent to calling F, then we say function G will a1, a2 ,..., an and other parameters are correctly forwarded to function F. Let's look at the second keyword "perfect". "perfect" forwarding is relative to other forwarding schemes. Among the seven forwarding schemes that have been proposed, only perfect forwarding can correctly implement the meaning of forwarding. Other schemes have the same or other problems. The following is a one-to-one introduction.

Forwarding Scheme 1: Use a constant left value for reference. Consider the following code.

 

 

 

 

1 void F (int)

2 {

3 cout <a <endl;

4}

5

6 template

7 void G (A &)

8 {

9 F ();

10}

 

 

 

We can call F (10) but cannot call G (10) When using a very large left value reference. That is, we cannot receive parameters of a very large right value.

 

 

 

Forwarding scheme 2: Use constant left value reference. Consider the following code.

 

 

 

 

1 void F (int &)

2 {

3 cout <a <endl;

4}

5

6 template

7 void G (const A &)

8 {

9 F ();

10}

 

 

 

When constant left value reference is used, function G can receive any type of value as a parameter, including the left value of a constant, the left value of a constant, the right value of a constant, and the right value of a constant. However, when the parameter type of F is a constant left reference, we cannot forward a constant left reference to a constant left reference.

 

 

 

Forwarding Scheme 3: Use a constant left value reference + constant left value reference. Consider the following code.

 

 

 

 

1 template

2 void G (A &)

3 {

4 F ();

5}

6

7 template

8 void G (const A &)

9 {

10 F ();

11}

 

 

 

Based on the analysis results of the preceding two schemes, we can conclude that this scheme is equivalent to overloading function G. In this case, we can receive any type of values as parameters and smoothly implement forwarding. However, because constant and extraordinary loads are used, when the number of parameters N is large, the function to be overloaded will increase exponentially (the Npower of 2 ), therefore, this solution is not feasible.

 

 

 

Forwarding Scheme 4: Use constant left value reference + const_cast.

 

 

1 template

2 void G (const A &)

3 {

4 F (const_cast ());

5}

 

This solution overcomes the disadvantages of solution 2. Now we can forward the constant left value reference to a very large left value reference. However, this introduces a new problem. If the F parameter is a constant left value reference, after G is called, we can use F to modify the left and right values of input constants, which is very dangerous.

 

 

 

Forwarding scheme 5: The parameter deduction rule of the constant left value reference + modification.

This scheme is similar to solution 1, but you need to modify the existing parameter deduction rules, that is, when you pass an extraordinary right value to the template type, it is deduced to the constant right value, this solves the problem that the parameter in solution 1 cannot receive a very large number of right values. However, because the existing parameter deduction rules are modified, the semantics of the existing code changes. Consider the following code.

 

 

 

 

1 template

2 void F (A &)

3 {

4 cout <void F (A & a) <endl;

5}

6

7 void F (const long &)

8 {

9 cout <void F (const long & a) <endl;

10}

 

 

 

Before modifying the parameter deduction rule, calling F (10) selects the second overload function, but after modification, it calls the first overload function, this brings compatibility issues to C ++.

 

 

 

Forwarding scheme 6: Right Value reference. Consider the following code.

 

 

1 template

2 void G (A &)

3 {

4 F ();

5}

 

In this solution, G cannot receive the left value because it cannot pass a left value to a right value reference. In addition, a problem also exists when passing a non-constant right value, because a itself is a left value, so when the F parameter is a reference of a non-constant left value, we can modify the incoming extraordinary right value.

 

 

 

Forwarding scheme 7: Right Value reference + modified parameter deduction rules.

To understand the modified parameter deduction rules, let's first look at the reference superposition rules:

1. T & + & = T &

2. T & + & = T &

3. T & + & = T &

4. T or T & + & = T &&

The modified parameter derivation rule for right-value reference is as follows: if the template parameter of the function template is A and the form parameter of the template function is A &, there are two types of discussions:

1. If the real parameter is T &, the template parameter A should be deduced as the reference type T &. (According to the 2nd point T & + & = T & and A & = T &, A = T & can be obtained &)

2. If the real parameter is T &, the template parameter A should be deduced as A non-reference type T. (A = T or T & + & = T &&, mandatory A = T)

After applying the new parameter deduction rules, consider the following code.

 

 

1 template

2 void G (A &)

3 {

4 F (static_cast ());

5}

 

When it is passed to G a left value (type = T), because the template is a reference type, it is implicitly converted to the left reference type T &. According to rule 1, template parameter A is deduced as T &. In this way, when G calls F (static_cast (a) internally, static_cast (a) is equivalent to static_cast (A) according to the reference superposition rule 2nd point, that is, static_cast (A), which is still a left value to forward to F.

When it is passed to G a right value (type = T), because the template is a reference type, it is implicitly converted to the right value reference type T &, according to Rule 2, template parameter A is deduced as T. In this way, when G calls F (static_cast (a) internally, static_cast (a) is equivalent to static_cast (A), so that the forwarded to F is still a right value (the unspecified right value reference is a right value ).

It can be seen that after this scheme is used, the left and right values can be correctly forwarded without any other problems. In addition, C ++ 11 provides a function template forward for convenient forwarding. The code after using forward can be simplified:

 

 

1 template

2 void G (A &)

3 {

4 F (forward ());

5}

 

To facilitate the comparison of various forwarding schemes, the following table lists their respective features.

 

Forwarding scheme: constant, constant, right, language modification known

 

1. The constant left value references the constant left value. The constant left value cannot be forwarded. The constant left value cannot be received.

2. Constant left reference constant left value constant no can forward constant left value reference to constant left value reference

3. constant reference + constant reference

Iv. Constant left value reference + const_cast extraordinary left value no can modify constant left value and constant right value unsafe

5. Extraordinary left value reference + modified parameter derivation rules the left value of a constant of

6. the right value reference cannot be forwarded. The left value of the constant cannot be forwarded. The left value of the constant is the right value that can be modified. It is not safe.

VII. Right Value reference + modified parameter deduction rule extraordinary left value constant extraordinary right value constant is not available now, so it is referred to as perfect forwarding

 

 

 

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.