C++ 如果结构具有不可复制的成员,那么如何初始化它?

C++ 如果结构具有不可复制的成员,那么如何初始化它?,c++,inheritance,C++,Inheritance,我想创建一个结构,它有一些基本成员和唯一的\u ptr,不能复制。我试图通过禁用copy并添加默认的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

我想创建一个结构,它有一些基本成员和唯一的\u ptr,不能复制。我试图通过禁用copy并添加默认的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
函数“int main()”中的
:
37:3:错误:调用'ListElem::ListElem()'时没有匹配的函数
37:3:注:候选人为:
25:2:注意:ListElem::ListElem(ListElem&&)
25:2:注意:候选者需要1个参数,提供2个参数
20:5:注意:constexpr ListElem::ListElem()
20:5:注意:候选者需要0个参数,提供2个
代码是:

// 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));
}
//示例程序
#包括
#包括
#包括
MyObj类{
公众:
虚拟~MyObj(){}
};
MyObj2类:公共MyObj{
公众:
虚拟~MyObj2(){}
};
结构列表{
std::唯一的ptr项目;
int一些_计数器=0;
ListElem()=默认值;
ListElem(ListElem const&e)=删除;
ListElem&运算符=(ListElem const&e)=删除;
ListElem(ListElem&&e)=默认值;
ListElem&运算符=(ListElem&&e)=默认值;
};
int main()
{
std::向量元素;
列表项{
std::unique_ptr(新的MyObj2()),
10
};
元素推回(标准::移动(项目));
}
我如何解决这个错误


编辑

我将构造函数更改为:

ListElem(std::unique_ptr<MyObj>&& _item, int _some_counter): item(_item), some_counter(_some_counter) {}
ListElem(std::unique_ptr&&u item,int_some_计数器):item(_item),some_计数器(_some_计数器){

但是现在我得到了
错误:使用deleted函数

可以从类中删除所有构造函数声明(1)。然后,该类将是一个聚合,并且可以通过聚合初始化(您正在尝试做的事情)进行初始化。请注意,无需手动删除复制构造函数或默认移动构造函数,两者都将自动执行

当然,另一种方法是提供一个双参数构造函数,它接受您想要传入的参数。请注意,即使在这种情况下,也不需要手动删除复制/移动操作&默认设置



(1) 请记住,
struct
class
都引入了类类型。它们之间的唯一区别是对基和成员的隐式访问控制(
public
private
);它们在其他方面是相同的。

在没有构造函数的情况下直接初始化结构称为聚合初始化。这只在某些情况下有效。例如,类本身不应该有任何构造函数(默认的构造函数可以)。看起来有些限制在c++14中被取消了,所以正如在另一个答案中所发布的,它在c++14或更高版本中运行良好。但不是在c++11中


问题是初始化成员某些计数器:这不允许对结构进行聚合初始化,请检查此处,说明类(结构)不应该没有默认的成员初始值设定项(从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));
}
//示例程序
#包括
#包括
#包括
MyObj类{
公众:
虚拟~MyObj(){}
};
MyObj2类:公共MyObj{
公众:
虚拟~MyObj2(){}
};
结构列表{
std::唯一的ptr项目;
输入一些计数器;
ListElem()=默认值;
ListElem(ListElem const&e)=删除;
ListElem&运算符=(ListElem const&e)=删除;
ListElem(ListElem&&e)=默认值;
ListElem&运算符=(ListElem&&e)=默认值;
};
int main()
{
std::向量元素;
列表项{std::uniqueptr(new MyObj2()),10};
元素推回(标准::移动(项目));
}

链接到代码:

让构造函数接受您想要传递的参数怎么样?或者根本没有声明或定义的构造函数(从而使结构成为聚合)?我很困惑,您只需要一个接受
std::unique_ptr
std::unique_ptr&&
int
的构造函数?您是否碰巧使用了c++11?不是c++14.c++14。我更新了同样值得一提的问题,而OP在IMO上遇到的障碍,
struct
也是类。关键字
struct
本身并不是一个聚合词。@StoryTeller Hm,我甚至没有想到这可能是个问题。我将尝试将其编入。我在上尝试了您的代码,但仍然得到错误。(我使用struct,因为我希望在默认情况下公开所有成员)@IterAtor您发布的链接不会指向代码。@IterAtor如果我将Coliru示例中的代码粘贴到cpp.sh,它将无法生成,您是对的。然而,在Coliru上,gcc和clang都编译它,即使是在C++14模式下。我倾向于说cpp.sh失败是他们使用的gcc版本的一个bug(4.9已经很旧了)。
ListElem(std::unique_ptr<MyObj>&& _item, int _some_counter)
: item(std::move(_item)), 
some_counter(_some_counter) 
{}
// 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));
}