首页 > 代码库 > c++OOP之复制控制 ------复制构造函数、赋值重载、析构
c++OOP之复制控制 ------复制构造函数、赋值重载、析构
本博文我们讨论OOP复制控制的一些内容;
首先考虑对象复制的时机: 非引用类型
1):根据一个类去显式或者隐式初始化一个对象;
2):复制一个对象,将它作为实参传给一个函数;
3):从函数返回时复制一个对象。(string tolittle(string word))
一个空类,编译器提供默认无参数构造函数、拷贝构造函数、赋值运算符以及析构函数,一共四个函数。(面试)
11.复制构造函数、赋值运算符以及析构函数,称为三法则,一旦提供了其中一个,务必提供其余两个。以String为例:a) 涉及到深拷贝、浅拷贝问题,所以需要提供拷贝构造函数b) 然后,为了保持一致,赋值运算符也应该实现深拷贝c) 既然实现深拷贝,那么必定申请了资源(例如内存),所以必然需要析构函数来手工释放。
一:复制构造函数:
复制构造函数调用的时机就是在对象复制的时候。方式有两种:
1):当用户不提供时,编译器自动为我们合成一个拷贝构造函数;
示例代码如下:
#include <iostream>#include <string>using namespace std;class Student { public: Student() {} Student(int id, const string&name, int age) :id_(id),name_(name),age_(age) {} void print() { cout << id_ <<":" << name_ <<":" << age_ << endl; } private: int id_; string name_; int age_;};int main(int argc, const char *argv[]){ Student s(11,"zhangsan",23); s.print(); Student s2(s); //执行此句,调用默认复制构造函数 s2.print(); return 0;}
2):用户自己定义:
放入class Student 的public中即可;
1 Student(const Student &s)2 {3 id_ = s.id_;4 name_ = s.name_;5 age_ = s.age_;6 }
复制构造函数之 深copy 和 浅copy;
含有指针成员变量的类在复制时,有两种选择:a) 复制指针的值,这样复制完毕后,两个对象指向同一块资源,这叫做浅拷贝 shallow copy(有可能出错)b) 复制指针所指向的资源,复制完毕后,两个对象各自拥有自己的资源,这叫做深拷贝 deep copy
示例代码:
1 #include "iostream" 2 #include "string.h" 3 using namespace std; 4 5 //copy String 时,仅仅复制指针的值 6 //导致析构时发生了问题 7 class String 8 { 9 public:10 String();11 String(const char*s);12 String(const String &s);13 ~String(); 14 void print()const15 {16 cout << str_ << endl;17 }18 private:19 char *str_;20 };21 String::String()22 :str_(new char(0))23 { }24 String::String(const char *s)25 :str_(new char[strlen(s)] +1)26 {27 ::strcpy(str_, s);28 }29 //程序结束时会调用析构函数,两个对象s1,s2必然会析构两次,而str_指向同一片区域;30 //当析构s1时,s1.str_所指向的区域被释放;而s2.str_ 也同时被释放31 //当析构s2时,由于s2.str_已经被s1.str_释放,所以会产生错误.32 String::String(const String &s)33 :str_(s.str_)34 {}35 36 /* 修改成以下即可:37 *String::String(const String &s)38 * :str_(new char[strlen(s)] +1)39 * {40 * ::strcpy(str_, s.str_);41 * }42 */43 String::~String()44 {45 delete[] str_; //注意46 }47 int main(int argc, const char *argv[])48 {49 String s("helloworld");50 s.print();51 52 String s2(s);53 s.print();54 return 0;55 }
二: 赋值运算符的重载:【因为我们自定义的类没有内置比较运算符(<、>、!=)】
示例代码如下:
1 #include <iostream> 2 #include <string.h> 3 using namespace std; 4 5 class String 6 { 7 public: 8 String(); 9 String(const char *s);10 String(const String &s);11 ~String();12 String &operator = (const String &s);13 size_t size()const //自己构造size函数14 {15 return strlen(str_);16 }17 18 void print()19 { cout << str_ << endl; }20 private:21 char *str_;22 };23 String::String()24 :str_(new char[1])25 { *str_ = 0; }26 27 String::String(const char*s)28 :str_(new char(strlen(s)+1))29 { ::strcpy(str_, s); }30 31 String::String(const String &s)32 :str_(new char(strlen(s.str_)+1))33 { ::strcpy(str_, s.str_); }34 35 String &String::operator = (const String &s)36 {37 if(this == &s)//自身赋值38 return *this;39 delete[]str_;40 str_ = new char(s.size() + 1 );41 ::strcpy(str_, s.str_);42 43 return *this;44 }45 46 String::~String()47 { delete[] str_; }48 49 int main(int argc, const char *argv[])50 {51 String s("helle");52 s.print();53 54 String s2;55 s2 = s; //赋值重载56 s2.print();57 58 s2 = s2 ; //注意自身赋值情形59 s2.print();60 61 return 0;62 }
禁止类复制和赋值的方法:
a):把 copy构造函数和复制运算符设为private;
b):只声明,不实现;
1 #include <iostream> 2 #include <string> 3 #include <vector> 4 using namespace std; 5 6 //no copy,no assignment 7 //google 推荐写法 8 #define DISALLOW_COPY_AND_ASSIGN(TypeName) 9 TypeName(const TypeName&); 10 void operator=(const TypeName&)11 12 class Test13 {14 public:15 Test(){}16 ~Test(){}17 18 private:19 Test(const Test&t);20 void operator=(const Test &t);21 };22 23 int main(int argc, const char *argv[])24 {25 Test t;26 27 Test t2(t);//error28 29 Test t3;30 t3 = t; //error31 32 return 0;33 }
a):如果一个类,不需要复制和赋值,那就禁用这种能力,这可以帮助避免大量潜在的bug。b):如果一个类,实现了像value一样的复制和赋值能力(意味着复制和赋值后,两个对象没有任何关联,或者逻辑上看起来无任何关联),那么就称这个类的对象为值语义(value semantics)。如果类不能复制,或者复制后对象之间的资源归属纠缠不清,那么称为对象语义(object semantics),或者引用语义(reference semantics)。
c++OOP之复制控制 ------复制构造函数、赋值重载、析构
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。