Blu*_*all 3 c++ debugging gcc destructor clang
请参阅下面的程序。程序应该打印 1,因为 1 计数器对象仍然存在,但是当用 GCC 编译时,它打印 0。为什么呢?这是编译器错误吗?仅当从不同范围返回时才会发生这种情况。删除 if 可以在所有编译器上完全修复它。
#include <iostream>
int counter = 0;
class Counter {
public:
Counter() {
counter++;
}
~Counter() {
counter--;
}
};
Counter test() {
if (true) { // REMOVING THIS FIXES IT
Counter c;
return c;
} else {
throw std::logic_error("Impossible!");
}
}
int main() {
Counter c = test();
std::cout << counter << std::endl; // 0 on GCC (incorrect), 1 on clang (correct)
return 0;
}
Run Code Online (Sandbox Code Playgroud)
在 C++ 中,从函数返回对象会在调用者上下文中复制构造该对象,然后在返回的函数中销毁复制的对象。在某些情况下,可以删除此副本。
Counter c;
return c;
Run Code Online (Sandbox Code Playgroud)
这称为返回值优化,在这种情况下不是强制性的。此处允许复制省略,但它是可选的。您使用的编译器之一会删除此副本,而另一个则不会。
如果没有复制省略,编译器将在调用者的上下文中复制构造返回的对象。
它Counter缺少复制构造函数,因此显示的代码无法记录复制构造对象的实例。
只需添加一个复制构造函数:
class Counter {
public:
Counter() {
counter++;
}
Counter(const Counter &) {
counter++;
}
~Counter() {
counter--;
}
};
Run Code Online (Sandbox Code Playgroud)
现在,无论有或没有复制省略,您都将获得预期的结果。
如果您在复制构造函数中设置断点,您将在从函数返回时看到断点命中(当使用不消除复制的编译器时)。
| 归档时间: |
|
| 查看次数: |
144 次 |
| 最近记录: |