Creation Point of an Automatic Variable

void foo() { //some code MyClass m(); //some more code } 

Does the C ++ standard provide the constructor of the MyClass class after calling //some code or is this unspecified behavior?

+4
source share
5 answers

The technical answer to this question is that the compiler ensures that the constructor is not running at all, since the line

 MyClass m(); 

not a variable declaration. Instead, it is the prototype for a function named m that takes no arguments and returns a MyClass . To do this in an object, you need to drop the parameters:

 MyClass m; 

Since this is such a confusion, there is a new syntax in C ++ 11 that you can use to initialize automatic objects. Instead of using parentheses, use curly braces, for example:

 MyClass m{}; 

This tells the compiler to use the constructor with a null value for MyClass as intended, since there is no way to interpret this as a function prototype.

If you make this change, the compiler guarantees that the constructor m will be executed after the first code fragment and before the second code fragment.

Hope this helps!

+4
source

First of all, MyClass m(); doesn't create any object, you probably meant MyClass m; . Yes, it is guaranteed that the object is created only after //some code run.

+3
source

No object is created here.

 MyClass m(); 

Declares a function with the name m , which takes no arguments and returns an object of type MyClass .

 MyClass m 

will create an object named m type MyClass and it will be guaranteed that the constructor for m will be called only when this line of code is executed.

+1
source

MyClass m(); → The object is not created here. Its just a function declaration that takes no parameters but returns a MyClass object.

If you need to create an object, just write MyClass m; or MyClass *m = new MyClass(); Yes, the MyClass constructor is called after some code.

0
source

Suppose you wanted to declare a variable, as already noted:

 void foo() { // {before} MyClass m; // {after} } 

Then the semantic constructor is executed after {before} and before {after}.

If this is done at run time, it is covered by the as-if rule. That is, in order to provide optimization, the Standard offers only guarantees about observable effects: regardless of the chosen execution model, the observable effects should be as if the code was executed without any optimization.

Observed effects, in particular, include:

  • changing volatile variables
  • system calls (including memory operations)

By default, a function whose definition is unknown should have observable effects.

A notable exception is the Elision copy optimization, which the Standard allows in some cases, even if the copy constructor may have observable effects.

Specifically, this means that this:

 int before(); int after(); void foo() { int n = 5; int const a = before(); n += a; MyClass m; int const c = after(); n += c; std::cout << n << "\n"; } 

The standard guarantees the following order:

  • before();
  • MyClass m;
  • after();
  • std::cout << n << "\n";

However, it is not guaranteed how n calculated. All that is known is that at the time of printing it will be equal to 5 + a + c , but regardless of whether the calculation is delayed just before printing or is performed impatiently every time a new item is available, it does not concern you : it does not change the observed behavior.

Therefore, the following two versions of foo equivalent:

 void foo_eager() { int n = 5; n += before(); MyClass m; n += after(); std::cout << n << "\n"; } void foo_lazy() { int const a = before(); MyClass m; int const c = after(); std::cout << (5 + a + c) << "\n"; } 
0
source

Source: https://habr.com/ru/post/1396779/


All Articles