Val*_*lus 4 c++ oop g++ copy-constructor compiler-optimization
最近我测试了一些C++深度和暗角,我对一个微妙的点感到困惑.我的测试实际上非常简单:
// problem 1
// no any constructor call, g++ acts as a function declaration to the (howmany())
// g++ turns (howmany()) into (howmany(*)())
howmany t(howmany());
// problem 2
// only one constructor call
howmany t = howmany();
Run Code Online (Sandbox Code Playgroud)
我对上线的期望是; 第一个howmany()构造函数调用将生成一个临时对象,然后编译器将使用该临时对象和copy-constructor来实例化t.但是,编译器的输出确实让我困惑,因为输出只显示一个构造函数调用.我的朋友们提到了我关于编译器传值优化的问题,但我们对此并不确定.我想了解这里发生了什么?
问题2的输出如下.问题1完全超出了对象实例化,因为编译器将其表现为函数指针声明.
howmany()
~howmany()
Run Code Online (Sandbox Code Playgroud)
我的测试类是:
class howmany {
public:
howmany() {
out << "howmany()" << endl;
}
howmany(int i) {
out << "howmany(i)" << endl;
}
howmany(const howmany& refhm) {
out << "howmany(howmany&)" << endl;
}
howmany& operator=(const howmany& refhm) {
out << "operator=" << endl;
}
~howmany() {
out << "~howmany()" << endl;
}
void print1() {
cout << "print1()" << endl;
}
void print2() {
cout << "print2()" << endl;
}
};
Run Code Online (Sandbox Code Playgroud)
这是最令人头疼的解析:
howmany t( howmany() );
Run Code Online (Sandbox Code Playgroud)
为了解决这个问题,你需要添加一组额外的parens:
howmany t( (howmany()) );
^ ^
Run Code Online (Sandbox Code Playgroud)
clang 在这里非常有用并警告你:
warning: parentheses were disambiguated as a function declaration [-Wvexing-parse]
howmany t( howmany() );
^~~~~~~~~~~~~
main.cpp:31:12: note: add a pair of parentheses to declare a variable
howmany t( howmany() );
^
( )
Run Code Online (Sandbox Code Playgroud)
另一种解决方法是使用C++ 11 统一初始化语法:
howmany t{ howmany{} };
^ ^^ ^
Run Code Online (Sandbox Code Playgroud)
更新
为了解决2您在问题中添加的部分,标准草案允许在某些情况下省略复制/移动结构.我们可以从12.8 复制和移动类对象第31段中看到这一点,它说:
当满足某些条件时,允许实现省略类对象的复制/移动构造,即使为复制/移动操作选择的构造函数和/或对象的析构函数具有副作用.在这种情况下,实现将省略的复制/移动操作的源和目标视为仅仅两种不同的引用同一对象的方式,并且该对象的销毁发生在两个对象的后期时间.在没有优化的情况下销毁.122在下列情况下,允许复制/移动操作的省略,称为复制省略
并包括以下项目:
当一个未绑定到引用(12.2)的临时类对象被复制/移动到具有相同cv-nonqualified类型的类对象时,可以通过将临时对象直接构造到目标中来省略复制/移动操作省略的复制/移动