拷贝删节法
copy elision method
本文关键字:拷贝 更新时间:2023-10-16
来自标准定义的复制省略方法:
在c++计算机编程中,拷贝省略指的是一种编译器优化技术,它可以消除不必要的对象复制。
让我们考虑下面的代码:
#include <cstdlib>
#include <iostream>
using namespace std;
int n=0;
struct C
{
C (int) {}
C(const C&) {++n;}
};
int main(int argc, char *argv[])
{
C c1(42);
C c2=42;
return n;
}
这行"return n"将返回0或1,取决于是否省略了副本。
还考虑以下代码:
#include <iostream>
struct C {
C() {}
C(const C&) { std::cout << "Hello World!n"; }
};
void f() {
C c;
throw c; // copying the named object c into the exception object.
} // It is unclear whether this copy may be elided.
int main() {
try {
f();
}
catch(C c) {
}
}
上面说
// copying the exception object into the temporary in the exception declaration.
//It is also unclear whether this copy may be elided.
所以我的问题是实现这种优化方法有多有用,如果有时结果是未定义的?一般来说,它使用的频率是多少?
重要的一点是标准明确地允许这样做,这意味着您不能假设复制构造函数的副作用将被执行,因为副本可能被省略。该标准要求复制构造函数的实现具有复制构造函数语义,也就是说,其总体目的是在您的域中生成与原始对象语义等效的第二个对象。如果您的程序符合这一点,那么优化将不会影响程序。
这是真的,另一方面,这是我能想到的唯一一种情况,在这种情况下,标准允许根据编译器的工作从同一个程序中获得不同的可见结果,但是你已经被建议在你的复制构造函数中不应该有副作用(或者更确切地说,你不能依赖于执行的副本的确切数量)。
至于是否值得,是的。在许多情况下,复制是相当昂贵的(我故意忽略了讨论中的c++ 11中的move-constructors)。考虑一个返回vector<int>
的函数,如果副本没有被省略,则需要另一个动态分配,复制所有向量内容,然后释放原始内存块这三个操作都可能是昂贵的。
或者,您可以强制用户更改他们的代码以创建一个空对象并通过引用传递它,但这会使代码更难阅读。
相关文章:
- 如何在没有数据拷贝的情况下从指针创建一个Eigen VectorXd对象
- 与浅拷贝构造函数和深拷贝构造函数混淆
- 使用复制构造函数修复浅拷贝
- C++ 一个lambda浅拷贝const Type&如果它被赋予一个命名捕获,如[copy=val](){}?
- 如何找到C++的伪拷贝操作
- 是否可以在C++中拼接缓冲区,零拷贝?
- 特征稀疏矩阵的零拷贝构造
- 在构造函数中浅拷贝字符串数组
- 如何将深拷贝构造函数实现到链表中?
- 为什么移动语义与动态 mem 分配中的浅拷贝具有相同的行为
- 在函数中传递带有指针成员的结构是浅拷贝或深拷贝在 C 中
- C++ 如何为地图创建浅拷贝构造函数
- 将 Android 内存映射到具有零拷贝的 GraphicBuffer
- 浅拷贝到协议缓冲区的字节字段中
- C++ 标准::字符串意外更改。我认为这个问题是关于深和浅拷贝的
- 如何正确制作抽象类的深拷贝?
- 为什么下面的类不对数组 arr 进行浅拷贝?
- 使用聚合初始化时,是否可以将无拷贝置换到地图中
- 将C 拷贝托转换为Python
- 在C++中使用浅拷贝而不是引用的原因