在用户声明的移动构造函数存在时使用复制构造函数

Use copy constructor while user-declared move constructor is present

提问人:Skylar 提问时间:12/12/2020 最后编辑:Ted LyngmoSkylar 更新时间:12/13/2020 访问量:1314

问:

在处理 .如果您能分享一些见解,我将不胜感激!unique_ptr

现在我们有了 .
Struct 是 class 的成员。
Struct 有一个成员。
BCBCstd::unique_ptr<A>

class A {
 public:
  A(int* id);
  A(const A& other);
  ~A() override;

 private:
  Microsoft::WRL::ComPtr<int> id_;
};

A.cpp

A::A(int* id) : id_(id) {
}

A::A(
    const A& other) {
  id_ = other.id_;
}

A::~A() = default;

A.K.(英语:A.K)

class B {
 public:
  struct C{
   public:
    C(
        int input_pad_id,
        Microsoft::WRL::ComPtr<int> input_id,
        std::unique_ptr<A>& input_a);
    C(const C& other);
    C& operator=(const C&);
    ~C();

    int pad_id;
    Microsoft::WRL::ComPtr<int> id;
    std::unique_ptr<A> a;
  };

  B();
  B(const B&) = delete;
  B& operator=(const B&) = delete;
  ~B() override;

 private:
  std::vector<C> c_item_;
};

B.cpp

B::B() = default;

B::~B() = default;

/* omitting some code related to operation logic */
...
c_item_.push_back({pad_id, id, nullptr});
...
/* omitting some code related to operation logic */

B::C::C(int input_pad_id,
        Microsoft::WRL::ComPtr<int> input_id,
        std::unique_ptr<A>& input_a)
    : pad_id(input_pad_id), id(input_id),
      a(std::move(input_a)) {}

B::C::~C() = default;

B::C::C(const C& other) = default;

B::C& B::C::operator=(const B::C& other) = default;

在构建时,我收到了以下错误日志:

error: no matching member function for call to 'push_back'
  c_item_.push_back({pad_id, id, nullptr});
  ~~~~~~~~~~^~~~~~~~~
../../buildtools/third_party/libc++/trunk/include\vector(711,36): note: candidate function not viable: cannot convert initializer list argument to 'const std::__vector_base<B::C, std::allocator<B::C>>::value_type' (aka 'const B::C')
    _LIBCPP_INLINE_VISIBILITY void push_back(const_reference __x);
                                   ^
../../buildtools/third_party/libc++/trunk/include\vector(714,36): note: candidate function not viable: cannot convert initializer list argument to 'std::vector<B::C>::value_type' (aka 'B::C')
    _LIBCPP_INLINE_VISIBILITY void push_back(value_type&& __x);
                                   ^
../B.cc(311,5): error: defaulting this copy constructor would delete it after its first declaration
    B::C::C(const C& other) = default;
       ^
../B.h(33,46): note: copy constructor of 'C' is implicitly deleted because field 'c_item' has a deleted copy constructor
    std::unique_ptr<C> c_item;

../../buildtools/third_party/libc++/trunk/include\memory(2528,3): note: copy constructor is implicitly deleted because 'unique_ptr<B>' has a user-declared move constructor
  unique_ptr(unique_ptr&& __u) _NOEXCEPT
  ^
../B.cc(315,65): error: defaulting this copy assignment operator would delete it after its first declaration
    B::C& B::C::operator=(const B::C& other) = default;
                ^
../B.h(33,46): note: copy assignment operator of 'C' is implicitly deleted because field 'c_item' has a deleted copy assignment operator
    std::unique_ptr<A> a;

../../buildtools/third_party/libc++/trunk/include\memory(2528,3): note: copy assignment operator is implicitly deleted because 'unique_ptr<A>' has a user-declared move constructor
  unique_ptr(unique_ptr&& __u) _NOEXCEPT
  ^

在这种情况下,我如何通过使代码使用具有用户声明的复制构造函数来解决此编译错误 移动构造函数?unique_ptr<A>

C++ 构造函数 复制 赋值

评论

0赞 Ted Lyngmo 12/12/2020
如果你需要一个提供复制功能的类似包装器,可以从头开始编写一个(或者创建一个包含但通过用户定义的复制 ctor/assignment 运算符提供复制的类)。让它在所有相同的情况下工作是很棘手的,但如果不需要 - 没问题。unique_ptrstd::unique_ptrunique_ptr

答:

4赞 Mooing Duck 12/12/2020 #1

让我删除一些格式:

 error: defaulting this copy constructor would delete it...
  C(const C& other) = default;
 ...because copy constructor of 'C' is implicitly deleted because field 'c_item' has a deleted copy constructor
  std::unique_ptr<C> c_item;

std::unique_ptr没有复制构造函数,因为它是唯一的。它无法复制。因此,任何包含 的 的 copy 构造函数都会被删除。因此,您的类没有复制构造函数。此外,您从未给它一个移动构造函数。std::unique_ptrC

插入方法(又名 push_back)可能必须调整大小,因此它必须移动或复制其元素,但没有复制或移动构造函数,因此您会收到编译器错误。std::vectorC

因此,解决方案是提供一个有效的复制构造函数和/或移动构造函数。如果它对你的任何内容都有意义,你可以通过制作指向的深度副本来给它一个复制构造函数,但我不知道是什么,所以我不能肯定地说。不过,创建一个移动构造函数几乎总是有意义的。CCAA

0赞 Red.Wave 12/13/2020 #2
template<typename X, typename D=std::default_deleter<A>, typename base=std::unique_ptr<A,D>>
struct not_unique_ptr
:   base {
    static_assert(std::is_same_v<base,std::unique_ptr<A,D>>);
    not_unique_ptr()=default;
    not_unique_ptr(not_unique_ptr &&) = default;
    not_unique_ptr(not_unique_ptr const& init)
    :   base{std::make_unique<A>(*init)};
    explicit not_unique_ptr(base && b) 
    :   base{std::move(b)}{};
    auto& operator=(not_unique_ptr &&) = default;
    auto& operator=(base&& rhs){
        base&{*this}=std::move(rhs);
    };
    auto& operator=(not_unique_ptr const& rhs){
        base&{*this}=base&&{not_unique_ptr{rhs}};
    };
};