自动变量的“创造点”

时间:2012-02-16 07:31:08

标签: c++ constructor initialization

void foo()  
{  
    //some code

    MyClass m();

    //some more code
}

C ++标准是否确保在 MyClass运行之后将调用类//some code的构造函数,或者是否为未指定的行为?

5 个答案:

答案 0 :(得分:4)

这个问题的技术答案是编译器会保证构造函数根本不运行,因为行

MyClass m();

变量声明。相反,它是一个名为m的函数的原型,它不带参数并返回MyClass。要将它变成一个对象,你需要删除parens:

MyClass m;

因为这是混淆的原因,所以在C ++ 11中有一个新的语法可用于初始化自动对象。而不是使用括号,使用花括号,如下所示:

MyClass m{};

这告诉编译器按预期使用MyClass的nullary构造函数,因为没有办法将上面的内容解释为函数原型。

如果进行此更改,编译器将保证m的构造函数在第一段代码之后和第二段代码之前执行。

希望这有帮助!

答案 1 :(得分:3)

首先,MyClass m();不会创建任何对象,您可能需要MyClass m;。是的,保证只有在//some code运行后才能创建对象。

答案 2 :(得分:1)

这里没有创建对象。

MyClass m();

声明一个名为m的函数,该函数不带参数并返回MyClass类型的对象。

MyClass m

会创建一个名为m的{​​{1}}类型的对象,是的,保证只有在执行该行代码时才会调用MyClass的构造函数。

答案 3 :(得分:0)

MyClass m(); - >这里没有创建对象。它只是一个函数声明,它不带参数但返回MyClass对象。

如果您需要创建对象,只需编写MyClass m;MyClass *m = new MyClass(); 是的,在一些代码之后调用MyClass的构造函数。

答案 4 :(得分:0)

假设你想要声明一个变量,正如已经说过的那样:

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

然后语义,构造函数在 {before} 之后和 {after} 之前执行。

执行期间是否保持这种情况由as-if规则涵盖。也就是说,为了允许优化,标准仅提供关于可观察效果的保证:无论选择何种执行模型,可观察效果应该是 - 如果代码已经执行而没有任何优化。

可观察到的影响尤其包括:

  • 修改volatile变量
  • 系统调用(包括内存操作)

默认情况下,定义未知的函数应具有可观察的效果。

值得注意的例外是复制Elision 优化,即使复制构造函数可能具有可观察的效果,标准也允许在许多情况下使用。

具体而言,这意味着给出:

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";
}

标准保证以下订购:

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

但是,保证的是n的计算方式。所有已知的是,在打印时,它将等于5 + a + c,但无论计算是在打印之前延迟还是在每次新元素可用时都急切地执行,这对您来说无关紧要:它不会改变可观察的行为。

因此,foo的以下两个版本是等效的:

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";
}