从复制省略方法的标准定义:在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;
}
Run Code Online (Sandbox Code Playgroud)
这行"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) {
}
}
Run Code Online (Sandbox Code Playgroud)
它说//在异常声明中将异常对象复制到临时对象中.//目前还不清楚是否可以省略此副本.所以我的问题是如果有时候结果是未定义的,那么实现这种优化方法有多大用处?一般来说,它的使用频率是多少?
Dav*_*eas 10
重要的是标准明确允许这一点,这意味着您不能假设复制构造函数的副作用将被执行,因为副本可能被省略.该标准要求复制构造函数的实现具有复制构造函数语义,也就是说,在整个目的中生成在域中与原始对象在语义上等效的第二个对象.如果您的程序符合该程序,则优化不会影响程序.
另一方面,这是我能想到的唯一情况,标准允许来自同一程序的不同可见结果取决于编译器的作用,但是你被告知你不应该有副作用.您的复制构造函数(或者更确切地说,您不能依赖于执行的确切复制数).
至于它是否值得,是的.在许多情况下,副本非常昂贵(我在讨论中故意忽略C++ 11中的move-constructors).考虑一个返回a的函数vector<int>
,如果没有删除副本,则需要另一个动态分配,复制所有向量内容然后释放原始内存块,这三个操作都可能很昂贵.
或者,您可以强制用户更改其代码以创建空对象并通过引用传递它,但这将使代码更难以阅读.