stackoverflow上的一个关于传递类对象的问题
今天在stackoverflow上看到有一个这样提问
说下面这段程序第二个输出语句有问题
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
class C {
public:
char* s;
C(char* s_) {
s=(char *)calloc(strlen(s_)+1,1);
strcpy(s,s_);
};
~C() {
free(s);
};
};
void func(C c) {};
void main() {
C o="hello";
printf("hello: %s\n",o.s); // works ok
func(o);
printf("hello: %s\n",o.s); // outputs garbage
};
我看了以后,大概分析了一下,原因是这样的
在c++中如果如果我们给一个类的对象赋值,或当形参传给其他函数时,假如类中含有指针类型的变量,默认c++会为我们拷贝指针而不会拷贝指针指向的内容。
上面的例子中,
func(o);
这个函数将实参o传给了形参,但是由于o的成员s是指针,所以实参与形参的指针指向了同一块内存空间,但是形参在函数结束后就析构掉了,
free(s);同时把指向的内存空间也清除了,所以当主程序再次返回的时候,原来的指针指向的内存空间已经没有了数据,故输出错误。
)
下面是一个外国同行写的解决方案
#include <iostream>
class C {
std::string s;
C(const std::string& s_)
: s(s_){}
};
std::ostream& operator<<(std::ostream& os, const C& c){
return os << c.s;
}
void func(C& c){
// do what you need here
}
int main(){
C c("hello");
std::cout << c << '\n';
func(c);
std::cout << c << std::endl;
return 0;
}
他这样的写法,是从另外一个角度写的,没有解决了指针的问题,其实,我感觉更好的方法是写一个复制构造函数,去专门管理指针的赋值。这样就不会容易出错了。