《剑指offer》面试题1:为类CMyString添加赋值运算符函数——C++拷贝构造函数与赋值函数
2013-08-16 23:36
267 查看
题中已给出CMyString的类定义,要求写赋值运算符函数。
关于拷贝构造函数:
定义:
拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参数是const类型,不可变的。例如:类X的拷贝构造函数的形式为X(X& x)。
调用情况:
当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的
对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
(1)一个对象以值传递的方式传入函数体
(2)一个对象以值传递的方式从函数返回
(3)一个对象需要通过另外一个对象进行初始化。
例如:
String a(“hello”);
String b(“world”);
String c(a); //用已初始化过的a去初始化新对象c,调用拷贝构造函数
c = b; // 调用了赋值函数
拷贝构造函数中为什么可以调用参数的私有成员:
成员访问控制符public、private、protected都是基于类而言的,如果一个类标记了private访问权限,其意思是——这个类以外的其他类(友元类除外)无法访问被private修饰的本类成员,但是本类自身是不受成员访问符限制的。
class my;
my类中有一个private的成员num,其意思是——成员num对于my类以外的其他类(友元类除外)都不可见(或不可访问),但my类自己并不受限于访问权限。
拷贝构造函数的参数是同类的引用,属于“本类”的范围。
关于赋值函数:
赋值函数4步实现:
首先注意传入的参数是const CMyString& rstring,常引用:
为什么是引用:如果参数不是引用而是实例,则从形参到实参相当于用已有对象去初始化一个新对象,要调用复制构造函数,造成不必要开销。
为什么是const:因为赋值函数内不会改变传入参数的状态,因此应该为传入的参数加上const。
(1)检查自赋值:判断传入的参数和当前实例(*this)是否为同一个,如果是同一个则直接返回。没有这一步的后果:一旦传入的是自身,则在第二步会delete自己,一旦释放自己的内存,参数也被释放了(自杀后不能复制自己),因此找不到需要复制的内容了。
(2)用delete 释放原有的内存资源。如果现在不释放,以后就没机会了,将造成内存泄露。
(3)分配新的内存资源,并复制字符串。
(4)返回本对象的引用:目的是为了实现stra = strb = strc这样的连续赋值,如果是void则不能实现连续赋值。另外返回引用而不是实例也是为了避免调用拷贝构造函数。
参考:
http://www.cnblogs.com/BlueTzar/articles/1223313.html C++拷贝构造函数(深拷贝,浅拷贝)
http://blog.chinaunix.net/uid-25808509-id-354211.html C++ 拷贝构造函数 赋值构造函数
#include<iostream> #include<cstring> using namespace std; class CMyString { public: CMyString(char* pdata = NULL); CMyString(const CMyString& rstring); CMyString& operator = (const CMyString& rstring); void Show(); ~CMyString(); private: char* m_pdata; }; CMyString::CMyString(char* pdata) //这里不能写char* pdata=NULL,一般如果函数声明和定义分开,则默认参数值在声明时 //写,定义时不用再写了 { /*m_pdata = pdata; 不能直接这样赋值:如果这样赋值,则新创建的m_pdata和pdata指向同一内存,m_pdata的操作直接影 影响pdata*/ if(pdata == NULL) { m_pdata = NULL; return; } int len = strlen(pdata); m_pdata = new char[len + 1]; strcpy(m_pdata,pdata); } CMyString::CMyString(const CMyString& rstring) { int len = strlen(rstring.m_pdata); //这里可以访问rstring的私有成员m_pdata m_pdata = new char[len + 1]; strcpy(m_pdata, rstring.m_pdata); } CMyString& CMyString::operator = (const CMyString& rstring) { if(this == &rstring) return *this; delete []m_pdata; m_pdata = NULL; m_pdata = new char[strlen(rstring.m_pdata)+1]; strcpy(m_pdata,rstring.m_pdata); } CMyString::~CMyString() { delete []m_pdata; } void CMyString::Show() { cout<<m_pdata<<endl; } int main() { char* pa = "abcde"; char* pb = "qperwdfaafda"; CMyString a(pa); a.Show(); CMyString b(pb); b.Show(); CMyString c(b); c.Show(); a = c; a.Show(); return 0; }
关于拷贝构造函数:
定义:
拷贝构造函数是一种特殊的构造函数,函数的名称必须和类名称一致,它的唯一的一个参数是本类型的一个引用变量,该参数是const类型,不可变的。例如:类X的拷贝构造函数的形式为X(X& x)。
调用情况:
当用一个已初始化过了的自定义类类型对象去初始化另一个新构造的对象的时候,拷贝构造函数就会被自动调用。也就是说,当类的
对象需要拷贝时,拷贝构造函数将会被调用。以下情况都会调用拷贝构造函数:
(1)一个对象以值传递的方式传入函数体
(2)一个对象以值传递的方式从函数返回
(3)一个对象需要通过另外一个对象进行初始化。
例如:
String a(“hello”);
String b(“world”);
String c(a); //用已初始化过的a去初始化新对象c,调用拷贝构造函数
c = b; // 调用了赋值函数
拷贝构造函数中为什么可以调用参数的私有成员:
成员访问控制符public、private、protected都是基于类而言的,如果一个类标记了private访问权限,其意思是——这个类以外的其他类(友元类除外)无法访问被private修饰的本类成员,但是本类自身是不受成员访问符限制的。
class my;
my类中有一个private的成员num,其意思是——成员num对于my类以外的其他类(友元类除外)都不可见(或不可访问),但my类自己并不受限于访问权限。
拷贝构造函数的参数是同类的引用,属于“本类”的范围。
关于赋值函数:
赋值函数4步实现:
首先注意传入的参数是const CMyString& rstring,常引用:
为什么是引用:如果参数不是引用而是实例,则从形参到实参相当于用已有对象去初始化一个新对象,要调用复制构造函数,造成不必要开销。
为什么是const:因为赋值函数内不会改变传入参数的状态,因此应该为传入的参数加上const。
(1)检查自赋值:判断传入的参数和当前实例(*this)是否为同一个,如果是同一个则直接返回。没有这一步的后果:一旦传入的是自身,则在第二步会delete自己,一旦释放自己的内存,参数也被释放了(自杀后不能复制自己),因此找不到需要复制的内容了。
(2)用delete 释放原有的内存资源。如果现在不释放,以后就没机会了,将造成内存泄露。
(3)分配新的内存资源,并复制字符串。
(4)返回本对象的引用:目的是为了实现stra = strb = strc这样的连续赋值,如果是void则不能实现连续赋值。另外返回引用而不是实例也是为了避免调用拷贝构造函数。
参考:
http://www.cnblogs.com/BlueTzar/articles/1223313.html C++拷贝构造函数(深拷贝,浅拷贝)
http://blog.chinaunix.net/uid-25808509-id-354211.html C++ 拷贝构造函数 赋值构造函数
相关文章推荐
- C++构造函数、拷贝构造函数、赋值运算符漫谈(二)——函数返回值
- 2.2.1 如下为类型CMyString 的声明, 请为该类型添加赋值运算符函数
- 【面试题一】类型转换关键字,空类对象模型,拷贝构造函数,赋值运算符函数
- 剑指offer-面试题1:赋值运算符函数
- C++构造函数、拷贝构造函数、赋值运算符漫谈(二)——函数返回值
- C++构造函数、拷贝构造函数、赋值运算符漫谈(二)——函数返回值
- 【面试题001】类型转换关键字,空类对象模型,拷贝构造函数,赋值运算符函数
- 【面试题001】类型转换关键字,空类对象模型,拷贝构造函数,赋值运算符函数
- 为类型CMyString的声明,请为该类型添加赋值运算符函数
- C/C++常见笔试面试题(二)——软件特性、fseek()函数、逗号运算符、左值和右值
- 编写String类的构造函数、析构函数以及赋值函数(C++面试题)
- 《剑指offer面试题4》替换空格——实现函数把字符串中每个空格替换成“%20”
- FAQ: c++ 函数名后添加 const void function1(int &id) const
- 面试题1:赋值运算符函数深度剖析
- 为Quick-Cocos2dx-2.26添加C++函数供Lua调用
- 多玩YY语音的面试题:C++中如何在main()函数之前执行操作?
- 关于C++中在函数中按值返回、临时对象、拷贝构造函数的一点理解
- 剑指offer面试题:如下为类型CMyString的声明,请为该类型添加赋值运算符函数。
- C++继承修改添加函数成员
- C++ 拷贝构造函数和重载赋值函数