函数返回对象 or 返回引用
一段有问题的代码
class String
{
private:
char * str;
public:
String():str(new char[1]) {str[0] = 0;};//无参的默认构造函数
const char * c_str() {return str;};
String & operator = (const char * s);//为什么要返回引用,返回对象会出错
String(const String & s)
{
str = s.str;
cout<<"copy"<<endl;
}
~String(){
delete [] str;
cout<<"Destruction"<<endl;
};
};
String & String::operator=(const char * s)
{
delete [] str;
str = new char[strlen(s) + 1];
strcpy(str,s);
return * this;
}
int main()
{
String s;
s = "GOOD LUCK";//等价于s.operator=("GOOD LUCK"),
cout<<s.c_str()<<endl;
//String s2 = "hello";会出错,这是初始化,不是赋值
return 0;
}
##返回值的讨论
void
好不好String
好不好- 为什么是
String &
考虑:a = b =c;
和(a = b) = c;//会修改a的值
分别等价于:
a.operator = (b.operator = (c));
(a.operator = (b)).operator = (c);
原则是维持原生运算符的特性
这样的String类就没有问题了吗?
正确的复制构造函数
String(const String & s)
{
str = new char[strlen(s.str)+1];
strcpy(str,s.str);
cout<<"copy"<<endl;
}
str = s.str是两个指针指向同一块内存,是指针的地址赋值 ,属于浅拷贝
strcpy后两个指针分别指向不同内存,内存中的内容一样,是地址指向的内存进行赋值,属于深拷贝
这样写复制构造函数后返回值是什么都不会编译出错
思考:是否可以这样理解,用对象作为返回值是,相当于返回一个复制出来的临时对象,如果函数外没有一个对象去接住这个临时对象,那么临时对象就会消亡,本例中的运算符重载就是这个情况,此时如果在复制构造函数中使用的是浅拷贝,那么原来的对象也就会跟着一起消亡,从而就会出错,使用深拷贝后就可以解决这个问题
如果不写复制构造函数,用的是编译器生成的缺省的复制构造函数,它做的是赋值的工作,会指向同一个内存,出现上面的问题
返回值是引用时,不会调用复制构造函数,没有这个问题产生
//返回值是对象
copy//重载运算符函数返回值时,调用复制构造函数
Destruction//没有对象接住返回的临时对象,临时对象消亡
GOOD LUCK//主函数的输出
Destruction//程序结束,对象消亡
//返回值是对象的引用时
GOOD LUCK//主函数的输出
Destruction//程序结束,对象消亡