首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C++中的时间、引用与三值算子

C++中的时间、引用与三值算子
EN

Stack Overflow用户
提问于 2013-09-20 14:15:21
回答 2查看 1.2K关注 0票数 7

我有以下基本代码:

代码语言:javascript
复制
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

代码语言:javascript
复制
const X& var = Y{"temporaryY"};
var.foo();

结果:

代码语言:javascript
复制
X::X() // base temporaryY
Y::Y() // temporaryY
Y::foo()
Y::~Y() // temporaryY
X::~X() // base temporaryY

X == OK

代码语言:javascript
复制
const X& var = X{"temporaryX"};
var.foo();

结果:

代码语言:javascript
复制
X::X() // temporaryX
X::foo()
X::~X() // temporaryX

Y X 通过函数= OK

代码语言:javascript
复制
const X& var = factory();
var.foo();

结果:

代码语言:javascript
复制
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?!

代码语言:javascript
复制
const X& var = false ? X{"temporaryX"} : Y{"temporaryY"};
var.foo();

结果:

代码语言:javascript
复制
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的析构函数要运行两次吗?
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-09-20 14:28:16

您所缺少的是,您的临时Y正在按片复制到绑定到您的const引用的隐藏临时X中。这就是您看到的最终析构函数,并解释了为什么Y比预期的时间早。复制的原因是三元操作符的“返回”只是一种类型。X不可能被视为Y,因此X是要使用的常见类型,从而导致额外的临时X对象。

请注意,这与“仅Y”测试用例不同,因为在该实例中创建了一个Y临时,然后立即尝试绑定到允许的const X&。在三元情况下,操作符本身将一个中间切片导入到操作符操作数的公共对象类型,在本例中为X

我相信您可以通过转换到父引用来避免临时切片,但是我无法访问C++11编译器来测试这个部分(除了问题中有些不完整的代码):

代码语言:javascript
复制
const X& var = false ? X{"temporaryX"} : static_cast<const X&>(Y{"temporaryY"});
票数 11
EN

Stack Overflow用户

发布于 2013-09-20 14:28:45

在作用域结束之前调用Y的析构函数?

因为创建了一个Y类型的对象,所以必须销毁它。因为它是一个临时对象,所以必须在表达式的末尾(在;之后)销毁它。

X::foo()被调用,而不是Y::foo()?

由于对象切片,它调用X:foo方法。该对象被切片为一个临时的X对象。

在第5.16/3节的标准中对此作了解释。

X的析构函数运行了两次吗?

X析构函数对Y临时对象调用一次,对var调用一次。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18918945

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档