我有以下基本代码:
struct X {
X(const char* descr) {...}
~X() {...} // Not virtual
virtual void foo() const {...}
};
struct Y : public X {
Y(const char* descr) {...}
~Y() {...} // Not virtual
virtual void foo() const {...}
};
const X& factory() {
static X sampleX{"staticX"};
static Y sampleY{"staticY"};
return X or Y depending of the test case;
};和4个测试用例:
Y == OK
const X& var = Y{"temporaryY"};
var.foo();结果:
X::X() // base temporaryY
Y::Y() // temporaryY
Y::foo()
Y::~Y() // temporaryY
X::~X() // base temporaryYX == OK
const X& var = X{"temporaryX"};
var.foo();结果:
X::X() // temporaryX
X::foo()
X::~X() // temporaryXY 或 X 通过函数= OK
const X& var = factory();
var.foo();结果:
X::X() // staticX
X::X() // base staticY
Y::Y() // staticY
X::foo() or Y::foo()
Y::~Y() // staticY
X::~X() // base staticY
X::~X() // staticXY 或 X 通过三元运算符= WTF?!
const X& var = false ? X{"temporaryX"} : Y{"temporaryY"};
var.foo();结果:
X::X() // base temporaryY
Y::Y() // temporaryY
Y::~Y() // temporaryY
X::~X() // base temporaryY
X::foo()
X::~X() // base temporaryY有人能解释一下为什么七层地狱:
Y的析构函数是在作用域结束之前调用的?X::foo()而不是Y::foo()X的析构函数要运行两次吗?发布于 2013-09-20 14:28:16
您所缺少的是,您的临时Y正在按片复制到绑定到您的const引用的隐藏临时X中。这就是您看到的最终析构函数,并解释了为什么Y比预期的时间早。复制的原因是三元操作符的“返回”只是一种类型。X不可能被视为Y,因此X是要使用的常见类型,从而导致额外的临时X对象。
请注意,这与“仅Y”测试用例不同,因为在该实例中创建了一个Y临时,然后立即尝试绑定到允许的const X&。在三元情况下,操作符本身将一个中间切片导入到操作符操作数的公共对象类型,在本例中为X。
我相信您可以通过转换到父引用来避免临时切片,但是我无法访问C++11编译器来测试这个部分(除了问题中有些不完整的代码):
const X& var = false ? X{"temporaryX"} : static_cast<const X&>(Y{"temporaryY"});发布于 2013-09-20 14:28:45
在作用域结束之前调用Y的析构函数?
因为创建了一个Y类型的对象,所以必须销毁它。因为它是一个临时对象,所以必须在表达式的末尾(在;之后)销毁它。
X::foo()被调用,而不是Y::foo()?
由于对象切片,它调用X:foo方法。该对象被切片为一个临时的X对象。
在第5.16/3节的标准中对此作了解释。
X的析构函数运行了两次吗?
X析构函数对Y临时对象调用一次,对var调用一次。
https://stackoverflow.com/questions/18918945
复制相似问题