【问题标题】:c++ Copy constructor and pointerc ++复制构造函数和指针
【发布时间】:2016-04-13 04:25:35
【问题描述】:

我正在上课 Place 使用这样的方法:

class  Place{

    protected:
    Keypoint* _kp;

    Place() {
        Keypoint* kp = new Keypoint();
        _kp = kp;
    };
    Place(const Place& cSource){
        delete _kp;
        _kp = cSource.makePointer();

        }
    virtual ~Place(){
        delete _kp;
    }

    virtual Keypoint* makePointer() const {
        return _kp->makePointer();
    }


};

因此是构造函数、析构函数和复制方法。

在我的主要操作中,我做了一些像AASS::graphmatch::Place ppp; AASS::graphmatch::Place p2(ppp); 这样简单的事情来尝试复制构造函数,并且我有一个巨大的段错误,valgrind 告诉我在副本中删除后我使用了Conditional jump or move depends on uninitialised value(s)。 Keypoint 中的方法makePointer 执行new 并返回一个指针Keypoint*

virtual Keypoint* makePointer() const {
    Keypoint* d = new Keypoint();
    return d;
}

我的理解是每个新的都应该使用 delete 来释放,这就是为什么我在调用 makePointer 之前使用 delete。所以这就是为什么我首先删除 _kp 以释放旧内存,然后将新创建的指针分配给它。

我无法理解为什么我有未初始化的值?

【问题讨论】:

  • 当您在复制构造函数中 delete _kp; 时,_kp 尚未为新对象初始化,因此您正在尝试 delete <garbage-ptr>
  • 这真的是复制构造函数吗?似乎每次都默认创建关键点(除非您使用一些看不见的全局变量)。这似乎违反了x == y 原则……
  • 我不确定在这种情况下x==y 原则是什么:S,但我所做的是我有一些从 Keypoint 继承的类并使用 makePointer( )。因此,根据 cSource 类型,我获得了一个 cSource 类的指针,它也是一个 Keypoint。
  • @Malc 评论有点草率,但我的意思是,如果您有一个复制构造函数,您可能希望复制复制构造的对象在某种程度上等于旧对象。假设Place p {}; Place p2{p}; bool eq = p==p2;,那么 eq 应该为真。您当然可以根据需要定义相等运算符,但在这种情况下,您获得的每个“副本”看起来都与默认构造的对象相同,在我看来,这并不是一个副本。特别是您希望 f(p)f(p2) 给出相同的答案,如果您在复制构建之前对 p 进行了更改,这将很难。
  • @patrik 我明白你的意思了:)!在这里很好,因为每个关键点一旦创建就无法更改。它们包含诸如类型之类的东西,该类型由相同关键点相同的字符串或相同关键点相同的颜色定义。因此,在我的应用程序中,一旦创建,关键点就永远无法更改。但是感谢您指出它,因为如果我改变它,我就不会意识到它,我可能会犯错误:)。

标签: c++ pointers copy-constructor delete-operator


【解决方案1】:

在您的复制构造函数中,您正在调用delete _kp;。但此时_kp 尚未初始化。

这不会有好的结局。

删除delete _kp; 行。更好的是,考虑使用基础成员初始化

Place(const Place& cSource) : _kp(cSource.makePointer())
{
}

甚至比这更好,考虑为您的Keypoint 成员使用像std::unique_ptr 这样的托管指针类。

【讨论】:

    【解决方案2】:

    您将复制构造函数编写为赋值运算符:

    Place(const Place& cSource){
        delete _kp;
        _kp = cSource.makePointer();
    
        }
    

    您可能需要一个赋值运算符,并且您可能还需要一个复制构造函数。但它们不是一回事。

    在进入复制构造函数时,_kp 持有垃圾,因此delete 是一个错误。

    【讨论】:

      【解决方案3】:

      您在复制构造函数中删除了一个未初始化的指针:

      Place(const Place& cSource){
          // delete _kp; // _kp is not initialized 
          _kp = cSource.makePointer(); // now _kp gets initialized
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-17
        • 2016-04-08
        • 2010-10-21
        • 2011-02-09
        相关资源
        最近更新 更多