2012-11-14 138 views
0

我有一个情况我有以下简要:在C++中临时克隆?

class K { 
    K clone() const{K cl; /* clone this to cl then */ return cl; } 
}; 
K* call_clone() 
{ 
    K k; 
    return new K(k.clone()); 
} 

编译器的优化后,将在本倍加复制?

或者:
会更有效的执行C*clone()

像这样:

class K { 
    K* clone() const { K*p=new K(); /* clone this to *p then */ return p; } 
}; 
K* call_clone() 
{ 
    K k; 
    return k.clone(); 
} 

(我问这个,因为即使K的浅拷贝可能是昂贵的,这将是在实践中的一类数据结构)

+2

我认为你需要阅读一些关于C++ *复制构造函数*,也可能*参考文献* – Roddy

+0

@罗迪:对于第二种情况 - 不一定。在使用多态性时,像他的第二个例子中的clone()可能是必需的。你可以在Java,C#等语言中看到所有类型的东西。 – 2012-11-14 14:08:52

回答

0

编译优化后,这会被双倍复制吗?

它取决于编译器。任何现代编译器都不会执行双重复制,这称为Return Value Optimization。它不取决于clone()的定义是否可用。

C * clone()会更有效吗?

不,它不会。动态内存管理(操作员新增/删除等)非常昂贵。它可能比执行双重副本更为昂贵,具体取决于您的副本构造函数实际执行的操作。

+0

请注意,RVO有点脆弱,所以您需要了解编译器如何/何时优化它。然而,'move'-return非常强大:如果你返回一个局部变量,编译器可以(通常是)'移动'。实现一个快速的'K(K &&)'移动构造函数,'call_clone'将最多调用2次移动。 'pImpl'模式可以帮助你快速移动构造函数,而其他时间则需要花费一些开销。你可能想知道你的'K'复制/移动的语义,并确保它们简单易懂...'K clone()'应该是一个拷贝构造函数,不应该吗? – Yakk

+1

使用'C * clone()'而不是'C clone()'的原因与优化无关。如果您只想在编译时复制类型已知的对象,则可以直接使用复制构造函数。除非需要动态分派,否则不使用函数clone。这几乎意味着返回一个指针。 –

+0

@JamesKanze:是的。如果碰巧有一个没有RVO的编译器,并且复制两次比调用'new'并复制一次更昂贵,那么使用'clone()'会更好。但现在很难想象这种情景IRL。 – 2012-11-14 15:06:51

0

传统clone()上创建一个副本堆,例如:

T* clone() { return new T(*this); } 

否则,人们可以简单地调用复制构造函数。

所以,call_clone()应该是这个样子:

K* call_clone() { 
    K k; 
    return k.clone(); 
} 
编译器优化后

,这会倍加复制?

如果clone()定义可用(该函数是内联的或由模板生成的),编译器可以优化创建局部变量并进行复制。

+1

C++中是否存在“传统克隆”这样的东西? – Roddy

+0

好吧,OpenCV'cv :: Mat'有'cv :: Mat clone()const;' –

+0

@Roddy:是的,没有。已经有数不清的尝试来标准化一个拥有深度拷贝的智能指针,通常被称为'value_ptr',而大的障碍一直是一个声称的clone()函数的性质。 –