我想创建一个结构,该结构具有一些原始成员和一个unique_ptr,该结构无法复制。我试图通过禁用复制并添加默认的move构造函数来解决此问题,但是它不起作用。编译器尝试查找2参数构造函数,但没有任何参数:
In function 'int main()':
37:3: error: no matching function for call to 'ListElem::ListElem(<brace-enclosed initializer list>)'
37:3: note: candidates are:
25:2: note: ListElem::ListElem(ListElem&&)
25:2: note: candidate expects 1 argument, 2 provided
20:5: note: constexpr ListElem::ListElem()
20:5: note: candidate expects 0 arguments, 2 provided
代码是:
// Example program
#include <iostream>
#include <memory>
#include <vector>
class MyObj {
public:
virtual ~MyObj(){}
};
class MyObj2 : public MyObj{
public:
virtual ~MyObj2(){}
};
struct ListElem {
std::unique_ptr<MyObj> item;
int some_counter = 0;
ListElem() = default;
ListElem(ListElem const& e) = delete;
ListElem& operator=(ListElem const& e) = delete;
ListElem(ListElem&& e) = default;
ListElem& operator=(ListElem&& e) = default;
};
int main()
{
std::vector<ListElem> elems;
ListElem item{
std::unique_ptr<MyObj>(new MyObj2()),
10
};
elems.push_back(std::move(item));
}
如何解决此错误?
修改
我将构造函数更改为此:
ListElem(std::unique_ptr<MyObj>&& _item, int _some_counter): item(_item), some_counter(_some_counter) {}
但是现在我得到error: use of deleted function
答案 0 :(得分:2)
您可以从类(1)中删除所有构造函数声明。然后,该类将是一个聚合,并且可以通过聚合初始化(您要尝试执行的操作)进行初始化。请注意,无需手动删除复制构造函数或默认将move构造函数删除,两者都会自动发生。
当然,替代方法是提供一个两参数构造函数,以接收要传递的参数。请注意,即使在这种情况下,也不需要手动删除和默认复制/移动操作。
(1)请记住,struct
和class
都引入了类类型。它们之间的唯一区别是对基和成员的隐式访问控制(分别为public
和private
);它们在其他方面是相同的。
答案 1 :(得分:1)
在没有构造函数的情况下直接初始化结构称为聚合初始化。这仅在某些情况下有效。例如。该类不应具有任何构造函数(默认值是可以的)。似乎在c ++ 14中解除了一些限制,因此如其他答案所述,它在c ++ 14或更高版本中工作正常。但不是在c ++ 11中。 https://gcc.godbolt.org/z/ZTFUz3
ListElem item{
std::unique_ptr<MyObj>(new MyObj2()),
10
};
在进行编辑时,失败的原因是您错过了移动unique_ptr
的过程。添加std::move
,它在两个版本中均应正常工作。
https://gcc.godbolt.org/z/uFmZvC
ListElem(std::unique_ptr<MyObj>&& _item, int _some_counter)
: item(std::move(_item)),
some_counter(_some_counter)
{}
答案 2 :(得分:0)
问题是成员 some_counter 的初始化:这不允许对该结构进行聚合初始化,请在此处https://en.cppreference.com/w/cpp/language/aggregate_initialization中进行检查,这说明该类(结构)不应没有默认的成员初始化器(从C ++ 11到C ++ 14)。
此处代码已更改:
// Example program
#include <iostream>
#include <memory>
#include <vector>
class MyObj {
public:
virtual ~MyObj(){}
};
class MyObj2 : public MyObj{
public:
virtual ~MyObj2(){}
};
struct ListElem {
std::unique_ptr<MyObj> item;
int some_counter;
ListElem() = default;
ListElem(ListElem const& e) = delete;
ListElem& operator=(ListElem const& e) = delete;
ListElem(ListElem&& e) = default;
ListElem& operator=(ListElem&& e) = default;
};
int main()
{
std::vector<ListElem> elems;
ListElem item { std::unique_ptr<MyObj>(new MyObj2()), 10};
elems.push_back(std::move(item));
}