返回值优化问题
Issue with return value optimisation
我在c++中读了一些关于RVO的文章,发现了一个奇怪的观察结果。我运行了以下代码。。
class myClass {
private:
int *ptr;
static int id;
public:
myClass() {
id++;
ptr = new int[10];
printf("Created %p id %d this %pn", ptr, id, this);
}
~myClass() {
delete[] ptr;
ptr = NULL;
printf("Deleted ptr id %d this %pn", this->id, this);
id--;
}
};
int myClass::id = 0;
myClass testFunc(myClass var) {
myClass temp;
return temp;
}
int main() {
myClass var1, var2;
testFunc(var1);
return 0;
}
我得到的o/p是
Created 0x9b14008 id 1 this 0xbfe3e910
Created 0x9b14038 id 2 this 0xbfe3e914
Created 0x9b14068 id 3 this 0xbfe3e91c
Deleted ptr id 3 this 0xbfe3e91c
Deleted ptr id 2 this 0xbfe3e918
Deleted ptr id 1 this 0xbfe3e914
Deleted ptr id 0 this 0xbfe3e910
testFunc调用中的临时复制变量实际上会引起一些问题。它删除var1的ptr成员,这可以通过调用指针0xbfe3e918中的析构函数来看到。在valgring下,此代码显示没有mem泄漏,但删除[]无效。
我有点困惑额外的析构函数是如何被调用的,为什么没有相应的构造函数来调用呢??
这实际上与返回值优化无关。只有当您使用testFunc
的结果时,RVO才会明显。
您看到的问题是,您的类只是使用默认的复制构造函数,因此当var
传递给testFunc
时,ptr
成员将被复制为常规指针,而不会创建它所指向对象的新副本。
因此,您最终会得到两个指向同一个底层int
数组的myClass
对象,当调用这两个对象的析构函数时,它们会两次尝试删除同一个int
数组。
按值传递var1
作为函数参数会创建一个副本。这是通过(隐式定义的)复制构造函数完成的,这就是为什么你的程序不打印任何东西——你只打印默认构造函数中的东西。
现在您遇到了一个大问题:对象的两个副本都包含指向同一数组的指针,并且在销毁时都会尝试删除它。这种双重删除是一个错误,会导致未定义的行为。
要修复它,要么遵循"三条规则"使类正确地可复制(要么不可复制);或者停止所有这些危险的原始内存,使用std::vector
或类似的方法为您正确管理数组。
当调用testFunc
时,var
被初始化为来自main的var1
的副本。这是使用默认的复制构造函数完成的,因此"缺少"构造函数调用。这只是调用了另一个构造函数。
所以问题是,现在var
是var1
的副本,这意味着var.ptr
必须具有与var1.ptr
相同的值。
1.解决方案是提供自己的复制构造函数来处理这种情况。一个解决方案是进行深度复制:
myClass(const myClass& o) {
id++;
ptr = new int[10];
memcpy(o.ptr, ptr, 10);
printf("Created copy %p of %p id %d this %pn", ptr, o.ptr, id, this);
}
2。另一种解决方案是使用shared_ptr
,它可以跟踪具有特定指针副本的对象的数量:
//int *ptr; //Replace this
shared_ptr<int> ptr; //With this
//Initialize ptr:
myClass():ptr(new int[10]) {
//...
}
// Also eliminate cleenup. It's handled by shared_ptr:
~myClass() {
printf("Deleted ptr id %d this %pn", this->id, this);
id--;
}
shared_ptr
方法的问题在于它们仍然共享相同的指针。这意味着它的行为不像通常预期的那样是一个副本。如果ptr
指向的值从未更改,则可以。
我更喜欢1的解决方案。
- 警告处理为错误这里有什么问题
- 最小硬币更换问题(自上而下方法)
- 为"adjacent"变量赋值时出现问题
- 我的神经网络不起作用 [XOR 问题]
- 无法理解代码背后的逻辑,这是在两个给定数字之间生成素数的优化问题
- 优化:黑客地球邮递员软件工程师实习生问题
- 关于使用类型转换优化除法代码的问题
- 优化递归问题以计算超级数字
- 在 c++ 中从 txt 文件中提取条目的代码优化问题
- [[GNU :: pure]]功能属性和线程的优化问题
- 由于Memcpy的问题,无法使用VS进行优化;被视为固有功能
- 编译器优化是否解决了线程安全问题
- 编译器优化问题
- 优化问题:整数加倍
- 求解整数约束优化问题
- 如何用Ceres求解大规模非线性优化问题
- 返回值优化问题
- 是否存在线程间共享变量的编译器优化问题
- 关于c++优化的问题
- iPhone代码优化问题