Boaz
Boaz

Reputation: 5084

"Creation point" of automatic variable

void foo()  
{  
    //some code

    MyClass m();

    //some more code
}

Does the C++ standard ensure that the constructor of class MyClass will be called after //some code has run, or is it unspecified behavior?

Upvotes: 4

Views: 134

Answers (5)

Matthieu M.
Matthieu M.

Reputation: 299920

Supposing that you meant to declare a variable, as has been remarked already:

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

Then semantically, the constructor is executed after {before} and before {after}.

Whether this holds during execution is covered by the as-if rule. That is, in order to allow optimizations, the Standard only offer guarantees about observable effects: whatever the execution model chosen, the observable effects should be as-if the code had been executed without any optimization.

Observable effects notably include:

  • modification of volatile variables
  • system calls (including memory operations)

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

The notable exception is the Copy Elision optimization, which the Standard allows in a number of cases even though the copy constructor might have observable effects.

Concretely, it means that given:

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 ordering:

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

What is not guaranteed, however, is how n is computed. All that is known is that at the moment of printing it, it will be equal to 5 + a + c, but whether the computation is delayed to just before printing or performed eagerly each time a new element is available is of no concern to you: it does not change the observable behavior.

Therefore, the two following versions of foo are 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";
}

Upvotes: 0

omggs
omggs

Reputation: 1153

MyClass m(); --> No object is being created here. Its just a declaration of function which takes no parameters but returns MyClass object.

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

Upvotes: 0

templatetypedef
templatetypedef

Reputation: 372814

The technical answer to this question is that the compiler will guarantee that the constructor isn't run at all, because the line

MyClass m();

is not a variable declaration. Instead, it's a prototype for a function called m that takes no arguments and returns a MyClass. To make this into an object, you need to drop the parens:

MyClass m;

Because this is such a source of confusion, in C++11 there is a new syntax you can use for initializing automatic objects. Instead of using parentheses, use curly braces, like this:

MyClass m{};

This tells the compiler to use the nullary constructor for MyClass as intended, since there's no way to interpret the above as a function prototype.

If you make this change, the compiler will guarantee that m's constructor is executed after the first piece of code and before the second piece of code.

Hope this helps!

Upvotes: 4

Naveen
Naveen

Reputation: 73443

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 is ran.

Upvotes: 3

Alok Save
Alok Save

Reputation: 206546

There is no object being created here.

MyClass m();

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

MyClass m

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

Upvotes: 1

Related Questions