c++ 类的复制函数

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ 类的复制函数相关的知识,希望对你有一定的参考价值。

我知道怎么写,但是我不知道为什么要写?

为什么类里面要有一个复制函数啊?

参考技术A b=a; //为什么这样写不会调用复制构造函数?
此处调用的是赋值运算符operator
=(const
a&);
只有当对象创建的时候才会调用构造函数,a
b(a);和a
b
=
a;//b在构造把a传给他调用拷贝构造函数
a
b;b
=
a;b已经被创建了不再会调用构造函数,调用的是缺省的赋值运算符。
参考技术B 你的意思是copy constructor咯,不一定非要自己写的,编译器已经为你自动生成了一个,只作浅复制用,深复制还是不能偷懒考编译器 参考技术C 你说的复制函数应该就是拷贝构造函数吧。
我先给你看个代码:
class A
public :
int *ptr;
~A();//此处代码略去,就是析构的时候释放掉ptr指向的空间,防止内存泄漏
;
void func(A a)
int main()
A a; //此处构造了一个类A的对象a。
func(a);//将a作为实参传递给func函数。
return 0;

看上去好像可以,但是在实参进行传值的时候,会在func内生成一个临时的A类型的对象,也就是形参。形参是在函数结束后会析构的。如果是用系统默认的拷贝构造函数的话,形参里面的ptr的内容和实参里面的ptr的内容相同,都是指向同一片空间,因为默认拷贝构造函数只是进行了浅拷贝,就是只是想实参的ptr的值赋给了形参的ptr,并未为形参的ptr分配空间,形参里面的ptr指向的空间在析构的时候会释放掉,也就无形中释放掉了实参的空间,但是实参并不知情...不明白的话可以Q我:461396291本回答被提问者采纳
参考技术D 你不知道为什么要写是因为一没有用到,等你用到的时候你自然会去写的。 第5个回答  2010-03-06 方便你用现有的对象去构造一个新的对象

防止 C++ 中的意外对象复制

【中文标题】防止 C++ 中的意外对象复制【英文标题】:prevent accidental object copying in C++ 【发布时间】:2010-11-23 07:40:10 【问题描述】:

在我们公司的编码标准中,我们被告知要“注意可以防止(意外)复制的方法”。

我不太确定这意味着什么,但假设它们的意思是如果不需要,我们应该停止复制类。

我能想到的如下:

    将类的复制构造函数设为私有。 将类的赋值运算符 (operator=) 设为私有。 明确类的构造函数(以防止使用不正确的变量创建类)。 对于所有执行内存分配和需要复制的类,请确保复制构造函数和赋值运算符执行深复制而不是浅复制。

我在正确的轨道上吗?有什么我可能错过的吗?

【问题讨论】:

实际上,我会理解这句话的意思是您应该注意这些事情并注意不要意外复制不应该复制的对象。但我知道什么?无论如何,这样的问题更有趣。 【参考方案1】:

是的,将赋值运算符和复制构造函数设为私有将阻止您使用标准方法创建对象的任何副本(但如果您确实需要一个对象的副本,您可以实现,例如 Copy() 方法,该方法将执行深拷贝)。

看看boost::noncopyable。

更新(回复 Tal Pressman):

...您应该注意这些事情并注意不要意外复制不应该复制的对象。

好吧,我想,任何意外复制都将使用赋值运算符或复制构造函数来执行。所以将它们设为私有实际上是有道理的:如果对象复制是昂贵的操作,那么复制必须是显式的:其他开发人员可以无意间间接调用复制操作,编译器会通知他,这是禁止的。

【讨论】:

【参考方案2】:

如果您的编码标准规定“注意可以防止(意外)复制的方式”,我猜他们不仅仅是在谈论防止类本身的复制,而是关于不必要的性能影响 / 使用类时意外复制。 C++ 新手在代码中不必要地浪费性能的主要原因之一是不必要的复制,通常是通过临时复制。编译器在决定何时不需要临时文件方面越来越好(请参阅"Want speed? Pass by Value",感谢 Konrad 的评论),但最好的办法是学习了解 C++ 中复制和临时文件的内部工作原理(以及其他)。对我来说,阅读 Efficient C++ 真的让我开始了。

【讨论】:

在考虑复制省略和 NRVO 时,您的第二点在很大程度上是错误的/误导性的。让专业人士说话:cpp-next.com/archive/2009/08/want-speed-pass-by-value 这实际上是一篇很棒的文章 - 我知道 RVO,但我上次深入研究它时仍在使用 VS2003,依赖编译器来让它正确处理更复杂的问题是有风险的类型。很高兴听到 C++0X 的问题越来越少 @MadKeithV:不要被提到的 C++0x 误导:那篇文章中的一切适用于当前的编译器和当前版本的 C++,没有什么是新的到 C++0x。 规范规则应该是“如有疑问,请检查汇编语言输出”:)。【参考方案3】:

如果您使用的是 boost,那么防止类被复制的最简单方法是从 noncopyable 派生您的类:

#include <boost/noncopyable.hpp>

class Foo : private boost::noncopyable


它比手动将复制构造函数和赋值运算符设为私有更清晰,并且具有相同的结果。

【讨论】:

我不认为他想阻止类被复制,而是他想防止它被意外地复制 我相信他会这样做,因为他将复制构造函数列为私有的选项之一。 尽管我很喜欢 boost,但我遇到过一些根本不允许使用 boost 的工作情况。【参考方案4】:

你在正确的轨道上。如果您不想使用 boost,您可以执行以下操作:将复制构造函数和复制赋值运算符设为私有并且不要实现它们。因此,如果您尝试复制实例,则会出现编译器错误。

【讨论】:

【参考方案5】:

从避免错误的角度来看,您的列表看起来很棒,例如由于对象隐式复制的共享指针,多次删除同一内存区域。

我希望这也是相关的;从“注意可以防止(意外)复制的方式”的声明中,您可能会认为这意味着“注意无意的不必要复制”。这将意味着可能影响性能的情况。在一个非常简单的示例中,您的编码约定可能意味着您应该更喜欢:

std::string text1( "some text" );

结束:

std::string text1 = "some text";

第二种情况会导致在调用赋值运算符(一种复制形式)之前创建一个临时字符串来保存“一些文本”,以用“一些文本”填充 text1。显然这是一个微不足道的例子,良好的实践表明你应该尽可能使用构造函数初始化(第一个例子)。

【讨论】:

感谢您的评论。这是我不知道的事情。因此,如果需要类型转换,请始终调用构造函数而不是使用赋值。 我不确定你对这个是否正确。两者都创建一个临时 char[]. 不,这完全是错误的。在这种情况下,所有现代编译器都会避免不必要的std::string 临时实例。 @the_drow - 两者都创建了一个临时的 const char[] 但只有第二个示例创建了一个不必要的临时 std::string。 @Konrad - 所有现代编译器应该避免它,但并非所有编译器都是现代的,也不需要优化它。据我所知,它不在标准范围内,但我可能是错的。 @J.Churchill:标准的 §12.2.2 明确提到实现可能会省略不必要的副本。所有中途现代编译器优化它。这可能意味着自 VC6 以来的所有编译器。所以从纯理论的角度来看,你是对的。但实际上并非如此。

以上是关于c++ 类的复制函数的主要内容,如果未能解决你的问题,请参考以下文章

C++ 中类的默认成员函数的问题(构造函数、析构函数、运算符 =、复制构造函数)(默认 ctor、dtor、复制 ctor)

C++ 类的复制控制

c++,类的对象作为形参时一定会调用复制构造函数吗?

C++学习基础六——复制构造函数和赋值操作符

在哪些情况下调用 C++ 复制构造函数?

C++中复制构造函数被调用的三种情况