void foo()
{
//some code
MyClass m();
//some more code
}
C++标准是否保证在运行
//some code
之后才会调用MyClass
类的构造函数,还是这是未指定的行为?void foo()
{
//some code
MyClass m();
//some more code
}
//some code
之后才会调用MyClass
类的构造函数,还是这是未指定的行为?对于这个问题的技术答案是编译器将确保构造函数完全不被执行,因为这一行代码
MyClass m();
不是变量声明。相反,它是一个名为m
的函数的原型,该函数不带参数并返回一个MyClass
对象。要将其转换为对象,您需要删除括号:
MyClass m;
MyClass m{};
这告诉编译器使用MyClass
的无参构造函数,因为没有办法将上述内容解释为函数原型。
如果您进行此更改,编译器将保证在第一段代码之后和第二段代码之前执行m
的构造函数。
希望这可以帮到您!
首先,MyClass m();
并不会创建任何对象,你可能想要使用的是MyClass m;
。是的,在运行//some code
之后保证会创建对象。
//some code
之后且在执行//some more code
之前被创建。 - Alok Save这里没有创建任何对象。
MyClass m();
声明一个名为m
的函数,该函数不接受任何参数并返回一个类型为MyClass
的对象。
MyClass m
将创建一个名为m
的MyClass
类型对象,是的,保证只有在执行该行代码时才会调用m
的构造函数。
假设你想要声明一个变量,正如已经提到的:
void foo() {
// {before}
MyClass m;
// {after}
}
从语义上讲,构造函数在{before}之后和{after}之前执行。
在执行过程中是否保持这种顺序由“as-if”规则覆盖。也就是说,为了允许优化,标准仅提供关于可观察效果的保证:无论选择哪种执行模型,可观察效果都应该像没有进行任何优化一样。
可观察效果包括但不限于:
volatile
变量的修改默认情况下,一个定义未知的函数被认为具有可观察效果。
值得注意的例外是“复制省略”优化,即使复制构造函数可能具有可观察效果,标准也允许在许多情况下使用它。
具体来说,这意味着给定:
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";
}
MyClass m();
--> 这里并没有创建对象,只是声明了一个不带参数但返回MyClass对象的函数。
如果你需要创建一个对象,只需写MyClass m;
或者MyClass *m = new MyClass();
是的,在一些代码之后会调用MyClass的构造函数。