use*_*670 4 c++ constructor copy-elision c++17
请考虑以下代码:
#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{}};
}
Run Code Online (Sandbox Code Playgroud)
我希望Thing thing{Thing{}};声明意味着临时对象的建设Thing使用默认的构造函数和建设类thing的对象Thing使用仅仅用创建的临时对象作为参数转移构造类.我希望这个程序被认为是不正确的,因为它包含一个被删除的移动构造函数的调用,即使它可能被省略.标准的class.copy.elision部分似乎也要求这样做:
即使呼叫被省略,也必须可以访问所选的构造函数
通过简化值类别保证复制省略的措辞似乎也不允许.
然而gcc 7.2(以及clang 4也是如此,但VS2017 仍然不支持保证复制省略)将编译此代码,只需移动构造函数调用即可.
在这种情况下哪种行为是正确的?
它不会构建一个不正确的程序.它完全摆脱了对删除函数的引用.提案中的适当措辞如下:
[dcl.init] bullet 17.6
如果初始化表达式是prvalue且源类型的cv-nonqualified版本与目标类相同,则初始化表达式用于初始化目标对象.[例子:T x = T(T(T())); 调用T默认构造函数来初始化x.]
这个例子进一步强化了这一点.因为它表示整个表达式必须折叠成单个默认构造.
需要注意的是,当由于值类别而省略副本时,删除的函数永远不会使用,因此程序不是指它.
这是一个重要的区别,因为其他形式的复制省略仍然使用复制c'tor,如下所述:
[basic.def.odr]/3
...选择复制或移动类类型对象的构造函数是odr-used,即使调用实际上已被实现省略([class.copy] ...
[class.copy]描述了允许(但不是强制)复制省略的另一种形式.如果我们向您的班级证明:
Thing foo() {
Thing t;
return t; // Can be elided according to [class.copy.elision] still odr-used
}
Run Code Online (Sandbox Code Playgroud)
应该使程序格式不正确.海湾合作委员会按预期抱怨它.
顺便说一下.如果您认为在线编译器中的前一个示例是魔术师技巧,并且GCC抱怨因为它需要调用移动c'tor.看看我们提供定义时会发生什么.
| 归档时间: |
|
| 查看次数: |
229 次 |
| 最近记录: |