【问题标题】:Compilation error with unique_ptrunique_ptr 的编译错误
【发布时间】:2017-08-26 19:41:21
【问题描述】:

知道为什么这不能编译:

#include <iostream>
#include <vector>

class A {
public:
  A() : m_Member( 1 ) {
    std::cout << "Constructor called." << std::endl;
  }
  A( A const & t_a ) {
    m_Member = t_a.m_Member;
    std::cout << "Copy constructor called." << std::endl;
  }

  virtual ~A() {
    std::cout << "Destructor called." << std::endl;
    m_Member = 0;
  }
  void play() { std::cout << "Number is: " << m_Member << std::endl; }
private:
  int m_Member;
};

class B {
public:
  B() {
    std::cout << "Main object created!" << std::endl;
  }

  B( B & b ) {
    for( std::unique_ptr< A >& val: b.m_Array ) {
      m_Array.push_back( std::unique_ptr< A >( new A( *val ) ) );
    }
  }

  virtual ~B() {
    std::cout << "Main object destroyed!" << std::endl;
  }

  A& get( size_t const Index ) {
    return *m_Array[ Index ];
  }

  void add( A& a ) {
    m_Array.push_back( std::unique_ptr< A >( new A( a ) ) );
  }

private:
  std::vector< std::unique_ptr< A > > m_Array;
};

B createB() {
  B b;
  A a1;
  A a2;
  b.add( a1 );
  b.add( a2 );
  return b;
}

int main() {
  B b = createB();
  A& temp = b.get( 1 );
  temp.play();
  return 0;
}

我明白了:

错误:没有匹配的构造函数用于初始化 'B' B b = createB();

另外,对于这个例子,有没有更好的方法来保存对象的向量?请注意,我故意在函数中创建对象,以便在销毁 B 之前删除传递给类 B 的对象。在这种情况下,引用包装器不起作用,因为它指向已被删除的对象。我试图通过引入 unique_ptr 来解决这个问题,但是我得到了这个错误。

【问题讨论】:

    标签: c++ c++11 smart-pointers stdvector unique-ptr


    【解决方案1】:

    B 不可复制,因为它拥有不可复制的 std::vector&lt;std::unique_ptr&lt;A&gt;&gt;

    您的“复制构造函数”实际上不是复制构造函数。改成这样:

    B(const B & b ) {
      for( const std::unique_ptr< A >& val: b.m_Array ) {
        m_Array.push_back( std::unique_ptr< A >( new A( *val ) ) );
      }
    }
    
    • 参数中的const B&amp; b 而不是B&amp; b
    • const std::unique_ptr&lt;A&gt;&amp; val: 而不是 std::unique_ptr&lt;A&gt;&amp; val:
    • 由于向量不可复制,编译器没有为B生成复制构造函数,并且createB作为临时返回的类型不能绑定到非常量引用。

    Demo

    【讨论】:

    • 成功了!非常感谢。我需要一些时间才能意识到 B 没有复制构造函数。
    【解决方案2】:

    如果你想“移动”它们,手动创建类,然后你可以移动指针。因为你有不可移动的对象,你不能移动它们,但你可以移动它们的指针,但你必须手动分配它们 newmalloc 这样对象就不会在函数@987654323的范围结束时被删除@。

    你手动创建这样的类:

    B *pointerToB = new B;
    

    在您的代码中:

    B createB() {
        B *b = new B;
        A a1;
        A a2;
        b->add( a1 );
        b->add( a2 );
        return b;
    }
    
    int main() {
        B *b = createB();
        A& temp = b->get( 1 );
        temp.play();
    
        delete b; // Do not forget to delete manually allocated object !!
        return 0;
    }
    

    最后你需要用指针删除对象:

    delete pointerToB;
    

    【讨论】:

    • 这是可以想象的最糟糕的解决方案。手动 newdelete 是您可能会做的最糟糕的事情之一,这是没有道理的。
    猜你喜欢
    • 2012-04-03
    • 1970-01-01
    • 2013-02-18
    • 2016-04-18
    • 1970-01-01
    • 2020-03-07
    • 2017-03-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多