C++中的临时、参考和三元运算符
Temporaries, references and ternary operator in C++
我有以下基本代码:
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
= 正常
const X& var = Y{"temporaryY"};
var.foo();
结果:
X::X() // base temporaryY
Y::Y() // temporaryY
Y::foo()
Y::~Y() // temporaryY
X::~X() // base temporaryY
只需X
= 正常
const X& var = X{"temporaryX"};
var.foo();
结果:
X::X() // temporaryX
X::foo()
X::~X() // temporaryX
Y
或通过功能X
= 确定
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() // staticX
Y
还是通过三元运算符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
析构函数运行两次?
您缺少的是,您的临时Y
正在按切片复制构造到绑定到您的常量引用的隐藏临时X
中。然后,这就是您看到的最后一个析构函数,也解释了为什么Y
比预期更早被销毁。制作此副本的原因是三元运算符的"返回"仅是一种类型。X
不可能被视为Y
因此X
是要使用的常见类型,从而引发额外的临时X
对象。
请注意,这与"Just Y"测试用例不同,因为在这种情况下,会创建一个临时Y
,然后立即尝试绑定到允许的const X&
。在三元情况下,运算符本身将中间切片诱导到运算符操作数的公共对象类型,在本例中为 X
。
我相信您可以通过强制转换为父引用来避免临时切片,但我无法访问 C++11 编译器来测试这一点(除了问题中有些不完整的代码):
const X& var = false ? X{"temporaryX"} : static_cast<const X&>(Y{"temporaryY"});
在范围结束之前调用 Y 的析构函数?
因为创建了 Y
类型的对象,所以必须销毁它。因为它是一个临时对象,所以必须在表达式的末尾(;
之后)销毁它。
X::foo() 被调用而不是 Y::foo()?
由于对象切片,它调用X:foo
方法。对象被切成一个临时X
对象。
这在标准§5.16/3中有解释。
X 的析构函数运行两次?
对于Y
临时对象调用一次X
析构函数,对var
对象调用一次析构函数。
相关文章:
- 三元运算符和 if constexpr
- 在 c++ 中三元运算符中不允许继续(关键字)吗?
- 三元运算符在返回语句中给出意外的结果
- Boost Spirit x3 条件(三元)运算符解析器
- 递归中三元运算符的奇怪行为
- 如何在三元条件运算符中添加换行符和连接? :在 C++ 中
- 错误:三元运算符无法在对象中正常工作"cout"
- 是否允许三元运算符在C++中计算两个操作数?
- 有条件地选择带有 decltype() 和三元运算符的类型
- 三元运算符在C++中的意外行为
- 有没有办法将 for 循环结果返回到像三元运算符这样的函数中?
- 变量值,在三元运算符之后
- 是否可以在C++中使用三元运算符在 if 语句中选择比较运算符?
- c++中的增量和三元运算符优先级
- C++中三元运算符的意外行为
- 用于返回开关的三元运算符
- 替换模板元编程中的三元运算符
- 三元运算符 '?:' 在 4.9.0 之前的 GCC 版本中推断出不正确的类型?
- 在 std::map 上使用三元运算符和 std::更大的附加参数
- C++中的三元条件运算符问题