如何强制执行复制 elision,为什么它不适用于已删除的复制构造函数?
How to enforce copy elision, why it won't work with deleted copy constructor?
我有一个无法复制的类。 复制这个会有问题。我想保证它永远不会被复制,所以我把它的复制构造函数deleted
:
class A {
public:
A();
A(const A&) = delete;
};
A fun() {
return A();
};
int main() {
A a = fun();
};
不幸的是,g++ 不会编译它的原因:
t.cc: In function ‘A fun()’:
t.cc:8:12: error: use of deleted function ‘A::A(const A&)’
return A();
^
t.cc:4:5: note: declared here
A(const A&) = delete;
^
t.cc: In function ‘int main()’:
t.cc:12:13: error: use of deleted function ‘A::A(const A&)’
A a = fun();
^
t.cc:4:5: note: declared here
A(const A&) = delete;
^
但这是一个非常明显的情况,应该使用复制 elision,所以不应该调用复制构造函数。为什么会这样?
直到 C++17 年,复制 elision 是编译器不需要做的优化,因此类必须是可复制的,因为编译器可能想要复制(即使它实际上不需要)。在 C++17 中,在许多情况下可以保证复制 elision,然后类就不需要复制 ctors。
另请参阅:
http://en.cppreference.com/w/cpp/language/copy_elision
http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0135r0.html
https://herbsutter.com/2016/06/30/trip-report-summer-iso-c-standards-meeting-oulu/(关于"保证复制省略"的部分)
也许您可以使用在类中声明复制构造函数的旧技巧,但实际上没有实现它?这应该让编译器满意,只要它没有实际调用复制 ctor。 我没有测试过,但我相信它应该适用于您的情况,直到 C++17 到来。
您还不能强制复制省略(请参阅其他答案)。
但是,您可以为类提供默认的移动构造函数,如果 RVO/NRVO 不可行,这将移动(因此不会复制)返回值。为此,您应该为移动构造函数添加= default
:
class A {
public:
A() = default;
A(const A&) = delete;
A(A&&) = default;
A& operator=(A&&) = default;
};
例
返回值优化(RVO 和 NRVO)并不意味着删除可复制或可移动所涉及的类型的要求。无论您是否获得 RVO,此要求都适用。
最可能的原因是(目前)没有强制执行复制省略。这是可能发生的优化,根据该优化是否应用于特定实现,代码编译或不编译是没有意义的。
在 C++17 中,RVO 将在某些情况下强制执行,并且将放弃可复制性和可移动性的要求。
- FLTK 2.0构建和演示,适用于VS2019的2011年左右的代码库
- C++17 - 使用自定义分配器的节点提取/重新插入 - 适用于 clang++/libc++,但不适用于 libstd
- "string.h"在构建适用于iOS的qt应用程序中找不到消息
- 适用于 WebView2 旧版本的示例应用程序
- 在 NVIDIA GEFORCE GTX 1050 上下载适用于 Windows 10 的 openCL 1.2
- __attribute__(优化(0))) 是否适用于"recursively"?
- 为什么 std::erase(std::erase_if) 不是适用于<algorithm>任何容器的模板?
- 使用一个参数的模板函数时出错(适用于 2)
- 使用 适用于 Android 和 iOS 的 tf-lite C++ API
- 为什么这适用于 G++ 而不是 CLANG?
- 适用于 macOS 的 Xcode 应用程序。这就是我设置从USB麦克风输入获取音频的方式。一年前工作,现在没有了。为什么
- 适用于 Linux 的 c++ 上的代理脚本
- 为什么我的 SFINAE 表达式不再适用于 GCC 8.2?
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- 有没有适用于Windows.lib文件的GNU二进制文件描述符(BFD)
- 模板函数仅适用于VS
- 如何在cmake中包含适用于g++或viceversa的库
- 适用于win32、linux、mac的POSIX C包装器
- WinDBG适用于从Visual Studio 2015保存的转储,但不适用于任务管理器。显示异常代码"not found"
- 适用于iOS和Android的C ++复制文件