【发布时间】:2017-09-06 09:47:39
【问题描述】:
考虑以下代码:
#include <iostream>
struct Thing
{
Thing(void) {std::cout << __PRETTY_FUNCTION__ << std::endl;}
Thing(Thing const &) = delete;
Thing(Thing &&) = delete;
Thing & operator =(Thing const &) = delete;
Thing & operator =(Thing &&) = delete;
};
int main()
{
Thing thing{Thing{}};
}
我希望Thing thing{Thing{}}; 语句意味着使用默认构造函数构造Thing 类的临时对象,以及使用刚刚创建的临时对象作为参数的移动构造函数构造Thing 类的thing 对象。而且我希望这个程序被认为是格式错误的,因为它包含对已删除移动构造函数的调用,即使它可能被省略。标准的 class.copy.elision 部分似乎也要求这样做:
即使调用被省略,所选的构造函数也必须是可访问的
Wording for guaranteed copy elision through simplified value categories 似乎也不允许这样做。
但是 gcc 7.2(以及 clang 4,但不是 VS2017 still does not support guaranteed copy elision)将 compile this code just fine 省略移动构造函数调用。
在这种情况下哪种行为是正确的?
【问题讨论】:
-
你为什么希望这里有一个临时的,而不是在
Thing thing{f()};那里f()返回一个Thing? -
另外,我怀疑“可访问”意味着“非私有”。
-
@BoPersson 不,它也适用于私有构造函数。
-
@BoPersson 我希望
Thing thing{f()};表示调用移动构造函数,并使用f()返回的临时参数调用一个参数。希望避免创建临时的开销。 -
通过简化值类别保证复制省略的措辞似乎也不允许这样做确实如此,但令人惊讶的是很少有人理解如何(或他们不急于回答)。所选答案仅显示示例,但它不是规范性措辞。并且示例前面的规范措辞并不能保证整个
T(T(T()))折叠成()或者重载决议不会选择复制/移动构造函数。
标签: c++ constructor c++17 copy-elision