C++复制构造函数错误地接受了参数



我有以下行为怪异的代码。到目前为止,我理解的流程是,display(line);将调用复制构造函数Line::Line(const Line &obj),并且line的引用将被传入。但是cout<<"[origin] *ptr="<<*obj.ptr<<endl;将打印[origin] *ptr=32767而不是[origin] *ptr=10

更奇怪的是,如果我取消对// int x=3;的注释,它将正确打印,但我真的不知道为什么。

您可以在以下位置找到可执行代码:https://www.onlinegdb.com/pjbPO0X1f

#include <iostream>

using namespace std;

class Line
{
public:
int getLength( void );
Line( int len );
Line( const Line &obj);
private:
int *ptr;
};

// constructor
Line::Line(int len)
{
ptr=&len;
cout<<"*ptr="<<(*ptr)<<endl;
}
// copy constructor
Line::Line(const Line &obj)
{
// int x=3;
cout<<"[origin] *ptr="<<*obj.ptr<<endl;
ptr = new int;
*ptr = *obj.ptr; // copy
}
int Line::getLength( void )
{
return *ptr;
}

void display(Line obj)
{
cout << "line=" << obj.getLength() <<endl;
}
int main( )
{
Line line(10);
display(line);
return 0;
}

您的程序调用未定义的行为(UB(。当你的构造函数完成:

Line::Line(int len)
{
ptr=&len;
cout<<"*ptr="<<(*ptr)<<endl;
} // ptr is dangling

指针ptr指向不再存在的局部变量lenptr现在处于悬空状态,任何对其取消引用的尝试都会调用UB。

你的程序可以做任何事情。你也可以看到一些奇怪的结果,比如添加CCD_;行为正确";。不要担心为什么会发生这种情况,这只是UB的结果。

这是一个常见的错误(尽管这是它的一个奇怪版本(。

这个代码是错误的

// constructor
Line::Line(int len)
{
ptr=&len;
cout<<"*ptr="<<(*ptr)<<endl;
}

使得ptr指向len,但是len是局部变量。当构造函数退出时,它将被销毁。这意味着您有一个指向已不存在的对象的指针。有时这被称为悬挂指针

然后在代码的后面使用这个指针

cout<<"[origin] *ptr="<<*obj.ptr<<endl;

由于指针现在无效,因此效果是不可预测的。

使指针变得困难的许多事情之一是,指针的生存期和它所指向的对象的生存期根本没有任何联系。这取决于你确保你的指针总是指向仍然"活着"的对象。

最新更新