C ++ Compiler optimization problems that come up with a question

Source: Internet
Author: User

I saw a problem in the past two days. It seems simple, but I have a lot of knowledge. The original question is as follows:


[Cpp]
# Include "stdafx. h"
 
Class Base
{
Public:
Base (){}
Virtual ~ Base (){}
Base (const Base & other); // declare only, not defined
Private:
Base & operator = (const Base & other );
};
 
Int _ tmain (int argc, _ TCHAR * argv [])
{
Const Base & B = Base (); // Why is the Link error not caused? The copy constructor should be called. However, I only declare that it is not defined!
 
Return 0;
}
# Include "stdafx. h"

Class Base
{
Public:
Base (){}
Virtual ~ Base (){}
Base (const Base & other); // declare only, not defined
Private:
Base & operator = (const Base & other );
};

Int _ tmain (int argc, _ TCHAR * argv [])
{
Const Base & B = Base (); // Why is the Link error not caused? The copy constructor should be called. However, I only declare that it is not defined!

Return 0;
}

I first thought of Compiler Optimization: I guess the compiler should be optimized: const Base & B = Base (); in this case, the syntax is as follows:

1. Call the Base Constructor

2. Call Base's value assignment function B = temporary object, but the compiler probably thinks that there is no need for such two steps to directly call the Base's constructor ....

Following the guidance of Xia A, I pointed out the problem:

When Base B = a, B has not yet been constructed, so we need to construct B first, and then assign values. Do you mean that the c ++ compiler designers can not optimize it? Therefore, this behavior is defined in all c ++, that is, Base B = a is Base
B (a), which is also the sweet of c ++ syntax.


Well .... So now we think that const Base & B = Base (); is changed to Base B (Base () by the compiler, so we should still call the default constructor and copy the constructor, no error is reported in the program !!!

Key character hero B appears:


[Cpp]
I personally think that the const Base & B = Base (); reference is directly bound to the anonymous object on the right, so the wood has a copy structure, therefore, it is related to whether the copy constructor defines wood.
See ISO/IEC 14882: 2003 (E)
8.5.3 References
4th 5 terms
-Otherwise, the reference shall be to a non-volatile const type (I. e., cv1 shall be const ).
I personally think that the const Base & B = Base (); reference is directly bound to the anonymous object on the right, so the wood has a copy structure, therefore, it is related to whether the copy constructor defines wood.
See ISO/IEC 14882: 2003 (E)
8.5.3 References
4th 5 terms
-Otherwise, the reference shall be to a non-volatile const type (I. e., cv1 shall be const). [cpp]
[Example:
Double & rd2 = 2.0; // error: not an lvalue and reference not const
Int I = 2;
Double & rd3 = I; // error: type mismatch and reference not const
-End example]
-If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2, "the reference is bound in one of the following ways (the choice is implementation-defined ):
-The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.
-A temporary of type "cv1 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. the reference is bound to the temporary or to a sub-object within the temporary.93)
[Example:
Double & rd2 = 2.0; // error: not an lvalue and reference not const
Int I = 2;
Double & rd3 = I; // error: type mismatch and reference not const
-End example]
-If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2, "the reference is bound in one of the following ways (the choice is implementation-defined ):
-The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object.
-A temporary of type "cv1 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. the reference is bound to the temporary or to a sub-object within the temporary.93)
Looking at this pile of English, I am confused again .... Calm down and read the following:

The key lies in this passage.


[Cpp]
-If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2, "the reference is bound in one of the following ways (the choice is implementation-defined): // if the right side of the initialization expression is a class type, the left side is a constant reference to the right value. In this case, the compiler can use either of the following methods ):
-The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object. // bind The reference directly to the right value.
-A temporary of type "cv1 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. the reference is bound to the temporary or to a sub-object within the temporary. // The temporary object is created, and the copy constructor is called to copy the temporary object to the right, and then bind the reference to the temporary object.
-If the initializer expression is an rvalue, with T2 a class type, and "cv1 T1" is reference-compatible with "cv2 T2, "the reference is bound in one of the following ways (the choice is implementation-defined): // if the right side of the initialization expression is a class type, the left side is a constant reference to the right value. In this case, the compiler can use either of the following methods ):
-The reference is bound to the object represented by the rvalue (see 3.10) or to a sub-object within that object. // bind The reference directly to the right value.
-A temporary of type "cv1 T2" [sic] is created, and a constructor is called to copy the entire rvalue object into the temporary. the reference is bound to the temporary or to a sub-object within the temporary. // The temporary object is created, and the copy constructor is called to copy the temporary object to the right, and then bind the reference to the temporary object.
Obviously, the VC and gcc I tested have chosen the first method to directly bind the reference to the right value ....~

Several Notes on reference, taken from the Network: http://www.bkjia.com/kf/201203/121502.html


[Cpp]
/*
(1) & this is not an address calculation, but an identifier.
 
(2) type identifier refers to the type of the target variable.
 
(3) When declaring a reference, it must be initialized at the same time.
 
(4) After the reference declaration is complete, it is equivalent that the target variable name has two names, namely, the original name and reference name of the target, and the reference name cannot be used as the alias of other variable names.
 
Ra = 1; equivalent to a = 1;
 
(5) declare a reference. Instead of defining a new variable, it only indicates that the reference name is an alias of the target variable name,
It is not a data type, so the reference itself does not occupy the storage unit, and the system does not allocate the storage unit to the reference.
Therefore, finding the address for the reference is to find the address for the target variable. & Ra and &.
 
(6) arrays cannot be referenced. An array is a collection composed of several elements, so an array alias cannot be created.
*/
/*
(1) & this is not an address calculation, but an identifier.

(2) type identifier refers to the type of the target variable.

(3) When declaring a reference, it must be initialized at the same time.

(4) After the reference declaration is complete, it is equivalent that the target variable name has two names, namely, the original name and reference name of the target, and the reference name cannot be used as the alias of other variable names.

Ra = 1; equivalent to a = 1;

(5) declare a reference. Instead of defining a new variable, it only indicates that the reference name is an alias of the target variable name,
It is not a data type, so the reference itself does not occupy the storage unit, and the system does not allocate the storage unit to the reference.
Therefore, finding the address for the reference is to find the address for the target variable. & Ra and &.

(6) arrays cannot be referenced. An array is a collection composed of several elements, so an array alias cannot be created.
*/

[Cpp]
The reference must follow the following rules as the return value:
 
(1) References to local variables cannot be returned. For details, refer to Item 31 of Objective C ++ [1. The main reason is that local variables will be destroyed after the function returns, so the returned reference becomes a reference of "no finger", and the program enters the unknown state.
 
(2) You cannot return a reference to the memory allocated by the new function. For details, refer to Item 31 of Objective C ++ [1. Although there is no passive destruction of local variables, this situation (returning a reference to the memory allocated by the new function) faces other embarrassing situations. For example, if a reference returned by a function only appears as a temporary variable and is not assigned to an actual variable, the space pointed to by the reference (allocated by new) cannot be released, cause memory leak.
 
(3) You can return a reference to a class member, but it is best to use const. This principle can be referred to Item 30 of Objective C ++ [1. The main reason is that when an object attribute is associated with a business rule, its value assignment is often related to some other attributes or the state of the object, therefore, it is necessary to encapsulate the value assignment operation in a business rule. If other objects can obtain the non-constant reference (or pointer) of this attribute, a simple value assignment to this attribute will damage the integrity of business rules.
 
(4) References and some Operator Overloading:
 
Stream operators <and>, which are often used consecutively, for example, cout <"hello" <endl; therefore, the return value of these two operators should be a stream reference that still supports these two operators. Other optional solutions include returning a stream object and returning a stream object pointer. However, for a returned Stream object, the program must re-(copy) to construct a new stream object. That is to say, two consecutive <operators are actually for different objects! This is unacceptable. If a stream pointer is returned, the <operator cannot be used consecutively. Therefore, returning a stream object reference is the only choice. This unique choice is critical. It illustrates the importance of reference and is irreplaceable. Maybe this is why the concept is introduced in C ++. Value assignment operator =. This operator can be used continuously like a stream operator, for example, x = j = 10; or (x = 10) = 100; the return value of the value assignment operator must be a left value, so that the value can be assigned. Therefore, it is referenced as the only return value choice of this operator.

From the column xiakan008
 

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.