复制构造函数——用相同的变量按值调用函数两次会导致问题
Copy constructor- calling function by value twice with same variable caused problems?
我被指向以下文章:
http://www.codeproject.com/Tips/78946/C-Copy-Constructor-in-depth,我们有代码:
class string
{
// constructor
string(char* aStr)
{
str = new char[sizeof(aStr)];
strcpy (str,aStr);
}
// destructor
~string()
{
del str;
}
char *getChars(){ return str; }
char* str;
};
void function (string str)
{
// do something
}
void main ()
{
string str("hello");
function(str);
function(str); // program crashes
}
我不明白为什么在main
中,第二次调用function
会有问题?当然,当str
被传递到第一次调用时,这只会是str
的副本,因此在function
中对str
所做的任何事情都不会影响在main
中声明的变量str
?
默认复制构造函数对对象进行逐位复制。换句话说,复制的是指针成员,而不是它所指向的对象。如果使用默认构造函数并且只对进行浅拷贝,则两个对象中的指针将指向同一个对象。
具体到你的问题:
第一次调用function(str)
时一切正常,当函数结束时,堆栈上的输入参数被销毁(这是str
的副本,但使用默认的复制构造函数,其指针指向与原始对象相同的位置),并且它的析构函数将被调用,删除指针指向的对象。
第二次调用function(str)
,当函数结束时,析构函数将尝试释放str
中指针所指向的地址,并崩溃。
为了避免这样的问题,应该定义自己的复制构造函数,它正确地复制对象,而不仅仅是指针,执行深度复制。
问题是string
类中的str
成员是一个指针。这意味着当创建字符串的副本时,该指针的值被复制,但指针的值只是一个内存位置。所以当你调用function(str)
时,它是在修改那个位置的内存,即使它没有修改指针的值。
默认情况下,c++只知道如何使用默认复制构造函数对数据进行浅层复制。所以,是的,对function
的第一次调用确实对str
进行了"复制",但这个复制并不是一个复制,因为被复制的是字符串类的char*
实例数据。例如,c++只是复制了一个地址,但不够聪明,无法为新字符串分配空间并复制内容。您必须自己使用自定义复制构造函数来完成。
str
的构造函数没有为后续对strcpy
的调用分配足够的字节。在那之后,所有的赌注都作废了。一旦解决了这个问题,就可以编写合适的复制构造函数和复制赋值操作符。
- g++的分段错误(在NaN上使用to_string两次时)
- 蛇在C++不会连续转两次
- 检查一个数组是否包含在另一个数组中,以相反的顺序,至少两次
- 从具有按值捕获的 lambda 移动构造 std::函数时,移动构造函数调用两次
- 我应该如何去缓解两次出现的cin?
- Realloc 两次无法在 Visual Studio 上运行
- 使用 getline(cin, var) 两次在进行字符串比较时会产生错误 (==)
- 为什么映射插入和 map.find() 的单次迭代比插入和 map.find() 的两次单独迭代慢得多
- C++析构函数调用两次,堆栈分配的复合对象
- 为什么参数在构造 std::thread 时移动两次
- 在钻石问题的求解中,为什么要虚拟地继承两次grand-parent类
- C OOP,读取文件的问题,EOF使用了两次,排行榜
- 矩阵移位两次时出现问题
- 不知道出了什么问题 - 两次程序隔离错误
- 复制构造函数——用相同的变量按值调用函数两次会导致问题
- 布尔值返回两次有问题(Arduino)
- C++两次传递函数指针导致问题
- Printf由于某种原因打印两次,cout似乎没问题
- 使用字符,我发现的唯一解决方案是static_cast两次。有没有办法解决这个问题?
- Makefile - section执行两次的问题