【问题标题】:C++ copy constructor incorrectly takes argumentC++ 复制构造函数错误地接受参数
【发布时间】:2020-12-20 06:23:51
【问题描述】:

我有以下行为奇怪的代码。目前我理解的流程是,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;
}

【问题讨论】:

  • 简单的评论是——不要这样写 C++ 代码。为什么在不需要的时候引入指针?

标签: c++ copy-constructor


【解决方案1】:

您的程序调用undefined behavior (UB)。当您的构造函数完成时:

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

指针ptr 指向一个不再存在的局部变量lenptr 现在悬空,任何解除引用的尝试都会调用 UB。

您的程序可以做任何事情。您还可以看到一些奇怪的结果,例如添加 int x = 3 导致您的程序“行为正确”。不用担心为什么会这样,这只是UB的结果。

【讨论】:

    【解决方案2】:

    这是一个常见错误(虽然这是一个奇怪的版本)。

    这段代码是错误的

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

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

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

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

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

    使指针变得困难的许多事情之一是指针的生命周期和它所指向的生命周期根本没有任何联系。确保您的指针始终指向仍然“活动”的对象,这取决于您。

    【讨论】:

      猜你喜欢
      • 2023-04-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-10
      • 2016-11-11
      • 1970-01-01
      相关资源
      最近更新 更多