以下面的课程为例
#include <iostream>
using namespace std;
class A{
private:
int a_;
int b_;
A(const A&) = delete;
A& operator=(const A&) = delete;
A(A&&) = delete;
A& operator=(A&&) = delete;
public:
A(int a, int b) : a_{a}, b_{b}{cout<<"constructed\n";}
void ephemeral() const{cout<<"operation\n";}
~A(){cout<<"destructed\n";}
};
A make_A(int a, int b){
return {a, b};
}
int main(){
make_A(1, 2).ephemeral();
return 0;
}
Run Code Online (Sandbox Code Playgroud)
构造对象,执行操作,然后对其进行破坏.
但是,我担心这是否有保证.我主要担心的是,由于标准给予编译器的自由,我是否能看到任何我不知道的影响.
我不认为copy-elision是一个因素,因为所有的移动和复制构造函数都被声明删除,所以它们怎么能被调用?
被调用的唯一构造函数是带有两个整数的构造函数.我可以确定这在编译器,平台和优化级别上的表现是否一致?
我怀疑答案是肯定的,但可能会有微妙之处.
当你return {a,b};直接构造返回值时.
不会创建临时的,逻辑的或其他的.不会出现任何缺陷.
此返回值在返回的上下文中可用main.你可以调用它的.ephemeral()操作.在完整表达式结束时,它超出了范围,除非您将它"存储"在A const&(引用生命周期扩展插入A&&)或(存储)中,或者存储在auto const&或者auto&&像这样的变量中:
auto&& a = make_A(1, 2);
a.ephemeral();
Run Code Online (Sandbox Code Playgroud)
但是,在上述情况下,不会发生复制.
这些操作都不会导致标准下的副本.
在某些情况下,您是正确的,可以省略复制构造.Elision是指两个物体的身份和生命时间合并在一起的时候.如果make_A阅读:
A make_A(int a, int b){
A r{a,b};
return r;
}
Run Code Online (Sandbox Code Playgroud)
r可以被省略为返回值.但是,在这里,编译器会要求A(A const&)或被A(A&&)定义,所以它不会用你的编译A.在实践中,一旦检查它们被定义,它就不会调用它们,因为r内部make_A将被省略为与返回值相同的对象make_A.
同样的,
A a = make_A(1,2);
Run Code Online (Sandbox Code Playgroud)
返回的临时值make_A被省略为与命名变量相同a.Elision是短暂的,所以这也可以将一个变量放在 一起make_A.在这种情况下,您还需要A(A&&)或A(A const&)存在.
通过删除移动/复制ctors,它们无法被调用,因此无法复制对象.每个构造函数只能调用一个析构函数(禁止手动构建或销毁).
如果代码试图调用它们,它将在编译时生成错误.
在C++ 17中,您甚至return A(a,b);可以获得类似的保证.
您也可以A a = make_A(1,2);和类似的保证发生.
这被描述为"保证省略",而是将一些操作变成"如何构建某些东西的描述".
因此,在某些情况下,您可以在C++ 03或C++ 11或C++ 14中执行需要移动或复制ctors的操作,但在C++ 17中,现在执行与"elision"类似的操作更长时间需要移动或复制ctors.
| 归档时间: |
|
| 查看次数: |
119 次 |
| 最近记录: |