【问题标题】:MyClass obj = MyClass(); Does 'MyClass()' refer to a temporary object here?MyClass obj = MyClass(); 'MyClass()' 在这里指的是临时对象吗?
【发布时间】:2017-08-15 17:38:01
【问题描述】:

考虑不涉及复制省略的情况(C++17 之前)。

来自 cppreference(再次假设 C++14):

在以下情况下会创建临时对象:

  • 将引用绑定到纯右值
  • 从函数返回纯右值
  • 创建纯右值的转换
  • lambda 表达式
  • 需要转换初始化程序的复制初始化
  • 构造 std::initializer_list 的列表初始化
  • 引用初始化为不同但可转换的类型或位域。

除了第一个之外的所有情况似乎都无关紧要,第一个似乎意味着 C++ 样式的引用绑定(int &&x = 5; BTW 在这种情况下我不明白临时对象在完整结束时被销毁的声明-表达式...,对象 5 所指的对象似乎没有在语句末尾被破坏)。

因此,据我了解,临时对象的概念仅包括那些保证被存储的对象(由于可能的省略,在我的情况下并非如此)。我对么?否则我在这里误解了什么?

顺便说一句,int x = 4;(或int x = 2 + 2; 中的2 + 2)中的MyClass()4 之间有什么区别吗?就像我可能不正确一样,第一个确实引用了一个临时对象,而另外两个没有...

【问题讨论】:

  • 它被计入“创建纯右值的转化”的情况下。 (是的,它看起来不像是转换,但标准将T()T(1)T(1,2) 组合在一起。)
  • @T.C.那么这样的事情是否仅适用于MyClass() 案例呢?不以我提出的4为例?那么造成这种差异的原因是什么?也许您可以创建一个答案?..考虑到您似乎与已经存在的答案相矛盾..
  • “创造prvalue的转换”是否仍会涵盖4?在这种情况下,它是从整数文字到纯右值整数的转换。
  • @NirFriedman 这些有什么区别吗?我认为“整数文字”正是整数纯右值的情况之一。再次来自 cppreference:以下表达式是纯右值表达式:文字(字符串文字除外),例如 42、true 或 nullptr;

标签: c++ c++14 temporary


【解决方案1】:

C++14 标准[1] 在 12.2 中说关于临时对象([class.temporary]):

类类型的临时对象在各种上下文中创建:将引用绑定到纯右值([...]),返回 纯右值([...]),创建纯右值([...],5.4)的转换,抛出异常([...]), 在一些初始化中([...])。

MyClass obj = MyClass(); 中,MyClass() 是函数式表示法中的显式类型转换,因此它是一个临时对象,因为它属于“创建纯右值的转换”。

这不适用于int x = 4; 中的4,因为该规则指的是“类类型”,但int 是“基本类型”。

另外,8.5 Initializers ([dcl.init]) 将第 (17.8) 条中的非类类型初始化器的语义定义为

否则,正在初始化的对象的初始值是初始化器的(可能转换的)值 表达。 [...]

对于类类型,调用(复制)构造函数。所以你需要一个(临时)对象来复制类类型,而不是“其他”类型。

[1]:实际上是N4296,但这应该没什么区别

【讨论】:

  • 也许您知道,如果您引用的片段 可能转换,例如 float x = 4;(int 到 float 转换),是否有一个临时对象用于4的原始整数?转换的结果是否是与“x”所指的一个单独的对象?不知道在这种情况下它是如何工作的..
  • 没有临时对象,因为prvalue4直接转换为prvalue4.f然后赋值。因此不需要int 类型的对象,只需一个值,因此不必创建临时对象。转换的结果又是prvalue,不是对象,所以不能和4是同一个对象。
  • 请问N4296 在哪里说MyClass() 是显式类型转换?好像没找到。 (如上所述,它看起来像是构造函数而不是转换)
【解决方案2】:

是的,它创建一个临时的,因为这是一个显式转换创建一个prvalue。

在此上下文MyClass obj = MyClass(); 中,MyClass()prvalue。从您提供的 qoute 来看,它符合“创建纯右值的转换”的情况,所以是的,创建了一个临时的。

实际上编译器会将这一行 MyClass obj = MyClass(); 转换为:(假设 MyClass 具有未删除的默认和复制构造函数)

MyClass _tmp{};  // (default-constructed)
MyClass obj = _tmp; // (copy-constructed)

第一行调用:MyClass::MyClass(this=&_tmp)

第二行来电:MyClass::MyClass(MyClass const&=tmp, this=&obj)

【讨论】:

    猜你喜欢
    • 2014-10-11
    • 1970-01-01
    • 2011-10-11
    • 1970-01-01
    • 2010-09-15
    • 2013-06-12
    • 1970-01-01
    相关资源
    最近更新 更多