为什么在这段代码中没有调用复制构造函数
Why is copy constructor not being called in this code
为什么在">const Integer运算符+(const Integer&rv("函数中没有调用Copy构造函数。是因为RVO吗如果是,我需要做些什么来防止它
#include <iostream>
using namespace std;
class Integer {
int i;
public:
Integer(int ii = 0) : i(ii) {
cout << "Integer()" << endl;
}
Integer(const Integer &I) {
cout << "Integer(const Integer &)" << endl;
}
~Integer() {
cout << "~Integer()" << endl;
}
const Integer operator+(const Integer &rv) const {
cout << "operator+" << endl;
Integer I(i + rv.i);
I.print();
return I;
}
Integer &operator+=(const Integer &rv) {
cout << "operator+=" << endl;
i + rv.i;
return *this;
}
void print() {
cout << "i: " << i << endl;
}
};
int main() {
cout << "built-in tpes:" << endl;
int i = 1, j = 2, k = 3;
k += i + j;
cout << "user-defined types:" << endl;
Integer ii(1), jj(2), kk(3);
kk += ii + jj;
}
如果我要注释掉复制构造函数,我确实会得到一个错误。我希望在运算符+返回时调用复制构造函数。以下是程序的输出
built-in tpes:
user-defined types:
Integer()
Integer()
Integer()
operator+
Integer()
i: 3 // EXPECTING Copy Constructor to be called after this
operator+=
~Integer()
~Integer()
~Integer()
~Integer()
是因为RVO吗。如果是,我需要做些什么来防止它?
是的。但由于编译器的返回值优化,它没有被调用。
如果你使用GCC,那么使用-fno-elide-constructors
选项来避免它
GCC 4.6.1手册称,
-fno elide构造函数
C++标准允许实现省略创建临时对象,该临时对象仅用于初始化同一类型的另一个对象。指定此选项将禁用该优化,并强制G++在所有情况下调用复制构造函数。
(N(RVO是最容易实现的优化之一。在大多数按值返回的调用约定中,调用者为返回的对象保留空间,然后将隐藏指针传递给函数。然后,函数在给定的地址中构造对象。也就是说,kk += ii + jj;
被翻译成类似于:
Integer __tmp;
// __rtn this arg
Integer::operator+( &tmp, &ii, jj );
kk += __tmp;
函数(在这种情况下,Integer::operator+
采用第一个隐藏参数__rtn
,它是指向要构造对象的sizeof(Integer)
字节的未初始化内存块的指针,第二个隐藏参数this
,然后是代码中函数的参数。
然后将该功能的实现转换为:
Integer::operator+( Integer* __rtn, Integer const * this, const Integer &rv) {
cout << "operator+" << endl;
new (__rtn) Integer(i + rv.i);
__rtn->print();
}
因为调用约定传递指针,所以函数不需要为随后将被复制的本地整数保留额外的空间,因为它只需将代码中的I
直接构建到接收到的指针中,就可以避免复制。
请注意,并不是在所有情况下编译器都可以执行NRVO,特别是如果函数中有两个本地对象,并且根据无法从代码中推断的条件(比如函数的参数值(返回其中一个。虽然你可以这样做来避免RVO,但事实是,它会使你的代码更复杂、效率更低、更难维护。
- 在c++中使用向量时,如何调用构造函数和析构函数
- C++:考虑但不调用构造函数的特殊性
- 对象实例化调用构造函数的次数太多
- 我使用向量来创建类对象列表.初始化向量时如何使用参数调用构造函数?
- C ++:通过大括号调用构造函数?
- 不能调用构造函数
- 赋值 boost::intrusive_ptr 而不调用构造函数?
- 在模板化类的构造函数中调用构造函数
- 如何为 std::vector 分配内存,然后稍后为某些元素调用构造函数?
- 为什么从另一个构造函数内部调用C++构造函数不修改类变量?
- 静态 std::map instatiation 在类的方法中调用构造函数吗?
- 有没有一种简单的方法可以在对象向量上调用构造函数?
- 我不明白在这个例子中什么时候调用构造函数
- 调用c++构造函数的不同方法
- 调用构造函数与将内联常量定义为默认参数
- 如何通过 Rust FFI 调用C++构造函数?
- "new"运算符是否总是调用构造函数?
- 无法调用构造函数
- 使用 "()" 调用构造函数不同于"{}"
- 确定是调用构造函数还是强制转换运算符的因素