`
从此醉
  • 浏览: 1044428 次
  • 性别: Icon_minigender_1
  • 来自: US
社区版块
存档分类
最新评论

C++拷贝构造函数和=赋值运算符详解

 
阅读更多

首先明确一点:

系统已经提供了默认的 拷贝构造函数 和 =复制运算符。 即所谓的浅拷贝。

但有时,我们必须提供自己重写。一般是在有指针的情况下重写。

举个简单的例子,没有指针,其实不必重写,只是为了演示:

class Fraction{
private:
	int fenmu; //分母
	int fenzi; //分子
public:
	Fraction(int x,int y){
		fenzi = x;
		fenmu = y;
	}
	Fraction(){}

	Fraction(const Fraction & fr);
	Fraction & operator=(Fraction& p);

	void display(){
		cout << fenmu << " " << fenzi;
	}
};

Fraction::Fraction(const Fraction & fr){
	cout << "test: use copy" << endl;
	fenmu = fr.fenmu;
	fenzi = fr.fenzi;
}

Fraction & Fraction::operator=(Fraction& fr){
	if(this == &fr)
		return *this;
	fenmu = fr.fenmu;
	fenzi = fr.fenzi;
	cout << "test use =" << endl;
	return *this;
}


int main(){
	Fraction f(1,2);
	Fraction f2(f); //use copy
	//f2.display();
	Fraction f3 = f2; // use copy
	Fraction f4,f5;
	f5 = f4 = f3; // use =
	//f5.display();
	return 0;
}


output:

test: use copy
test: use copy
test use =
test use =


如果有指针,则需要深拷贝:

#include <iostream>
using namespace std;
class CA
{
 public:
  CA(int b,char* cstr)
  {
   a=b;
   str=new char[b];
   strcpy(str,cstr);
  }
  CA(const CA& C)
  {
   a=C.a;
   str=new char[a]; //深拷贝
   if(str!=0)
    strcpy(str,C.str);
  }
  void Show()
  {
   cout<<str<<endl;
  }
  ~CA()
  {
   delete str;
  }
 private:
  int a;
  char *str;
};

int main()
{
 CA A(10,"Hello!");
 CA B=A;
 B.Show();
 return 0;
} 

通过拷贝相同类的另一个对象的状态来初始化一个对象。
使用:当通过数值传递,通过数值返回,或明确拷贝一个对象

赋值运算符

返回什么:一般通过引用返回*this,就是说用户自己定义的类的赋值遵守和内部类型相同的约定,赋值也可用作表达式,也即能够级联

自我赋值语法上没有任何错误,但如果你没有很好的实现赋值运算符,那么灾难可能就在等着你。
所以你必须确保自我赋值无害,也就是要加入自我赋值的检测
CAssignment& CAssignment::operator=(const CAssignment& a)
{
    if( this == &a )
        return *this;
    //….赋值该作的工作
}


保证赋值运算符只有两种结果:完全成功、原封不动留下对象并抛出异常
CAssignment& CAssignment::operator=(const CAssignment& a)
{
    if( this == &a )
        return *this;

    CTemp* t = new CTemp;
    //…..
    delete _tmp;
    _tmp = t;
    return *this;
}

派生类使用赋值运算符

派生类中的赋值运算符首先调用其直接基类赋值运算符(对声明在基类里的成员对象赋值),然后再调用它的成员对象的赋值运算符(改变在派生类里声明的那些成员对象)。这些赋值通常应该与基类和成员对象在该类的定义里出现的次序相同。

CDerived& CDerived::operator=(const CDerived& r)
{
	CBase::operator=(r);
	_c = r._c;
	return *this;
}

重载赋值运算符的正确形式:

c++的设计者stroustrup下了很大的功夫想使用户自定义类型尽可能地和内部
类型的工作方式相似。为此他做了很多努力(如重载运算符,写类型转换函
数和拷贝构造函数,等等)。而你也该继续做下去。
让我们看看赋值。用内部类型的情况下,赋值操作可以象下面这样链起来:
int w, x, y, z; w = x = y = z = 0;
所以,你也应该可以将用户自定义类型的赋值操作链起来:
CString w, x, y, z; // MFC “自定义”的类型
w = x = y = z = "hello";
因为赋值运算符的结合性天生就是由右向左,所以上面的赋值可以解析为:
w = (x = (y = (z = "hello"))); <=>
w.operator=(x.operator=(y.operator=(z.operator=("hello"))));

这个格式说明了w.operator=, x.operator=和y.operator=的参数是前一个
operator=调用的返回值。所以operator=的返回值必须可以作为一个输
入参数被函数自己接受。一般情况下operator=输入应该是类对象或
类对象的引用,从效率来说后者好过前者 ,所以输入和返回的都应
是类对象的引用。
又因为有
int x, y,z; (x = y) = z ;
所以如下语句也应正确
CString x, y, z; ( x = y) = z;
那么operator=的返回不能是const(因为常量不能赋左值)
又有
CString x; x = “Hello”; <=>
const CString temp(“Hello”); //产生临时对象,为什么是const
x = temp;
所以为保证上面的语句成立, operator=的输入应是const
所以最好的实现是 T& operator=(const T&);




分享到:
评论

相关推荐

    详解C++ 拷贝构造函数和赋值运算符

    本文主要介绍了拷贝构造函数和赋值运算符的区别,以及在什么时候调用拷贝构造函数、什么情况下调用赋值运算符。最后,简单的分析了下深拷贝和浅拷贝的问题。有需要的朋友可以看下

    详解C++中构造函数,拷贝构造函数和赋值函数的区别和实现

    C++中一般创建对象,拷贝或赋值的方式有构造函数,拷贝构造函数,赋值函数这三种方法。下面就详细比较下三者之间的区别以及它们的具体实现 1.构造函数 构造函数是一种特殊的类成员函数,是当创建一个类的对象时,它...

    C++ 赋值构造函数注意点介绍

    您可能感兴趣的文章:浅谈c++构造函数问题,初始化和赋值问题详解C++ 拷贝构造函数和赋值运算符详解C++中对构造函数和赋值运算符的复制和移动操作C++中复制构造函数和重载赋值操作符总结深入C++中构造函数、拷贝构造...

    详解c/c++赋值函数(重载=号运算符)

    首先c++里的各种运算符都是用函数实现的,比如=,就等号函数。 所以当用=给一个对象赋值的时候,实际调用的是=号所对应的=号函数。 分析下面的代码 ... //拷贝构造函数 Test(const Test &t){ cout &lt;&lt; Co

    C++ 中类的拷贝、赋值、销毁的实例详解

    和成拷贝构造函数的操作是将其参数的各个成员拷贝到正在创建的对象中去,每个成员的类型决定了他是如何被拷贝的:对类类型的成员,会使用其拷贝构造函数,内置类型的成员则是直接拷贝,虽然我们不能直接拷贝一个数组...

    c++学习经典图书:C++ 编程思想(全).rar

    全书共分十八章,内容涉及对象的演化、数据抽象、隐藏实现、初始化与清除、函数重载与缺省参数、输入输出流介绍、常量、内联函数、命名控制、引用和拷贝构造函数、运算符重载、动态对象创建、继承和组合、多态和虚...

    C++11unique-ptr智能指针详解.pdf

    3) 基于 unique_ptr 类型指针不共享各⾃拥有的堆内存,因此 C++11 标准中的 unique_ptr 模板类没有提供拷贝构造函数,只提供了移动构造 函数。例如: 1. std::unique_ptr&lt;int&gt; p4(new int); 2. std::unique_ptr...

    C++11unique-ptr智能指针详解(1).pdf

    3) 基于 unique_ptr 类型指针不共享各⾃拥有的堆内存,因此 C++11 标准中的 unique_ptr 模板类没有提供拷贝构造函数,只提供了移动构造 函数。例如: 1. std::unique_ptr&lt;int&gt; p4(new int); 2. std::unique_ptr...

    C++空类详解

    // 默认拷贝构造函数~Empty(); // 默认析构函数Empty& operator=( const Empty& ); // 默认赋值运算符Empty* operator&(); // 取址运算符const Empty* operator&() const; // 取址运算符 const 给出一个例子: ...

    C++智能指针-unique-ptr智能指针详解.pdf

    3) 基于 unique_ptr 类型指针不共享各⾃拥有的堆内存,因此 C++11 标准中的 unique_ptr 模板类没有提供拷贝构造函数,只提供 了移动构造函数。例如: 1. std::unique_ptr&lt;int&gt; p4(new int); 2. std::unique_ptr...

Global site tag (gtag.js) - Google Analytics