c++17在编译时将带有已删除复制构造函数的类添加到std::vector

c++17 add class with deleted copy constructor to std::vector at compile time

本文关键字:添加 构造函数 vector std 复制 删除 编译 c++17      更新时间:2023-10-16

下面是我用已删除的复制构造函数和复制赋值运算符定义的一个类。这是必须作出的唯一假设。

class MyClass
{
public:
explicit MyClass(int i) : i(i) {}
MyClass(const MyClass&) = delete;
MyClass& operator=(const MyClass&) = delete;
MyClass(MyClass&& other) :
i(std::move(other.i))
{}  
MyClass& operator=(MyClass&& other) {
i = std::move(other.i);
return *this;
}   
private:
int i;
};

目标是在编译时将我的类添加到std::向量中。

int main()
{
std::vector<MyClass> v{MyClass{0}, MyClass{1}, MyClass{2}};
return 0;
}

我的编译器告诉我STL需要使用我删除的副本构造函数MyClass::MyClass(const MyClass&),但有什么办法可以解决这个问题吗?

我已经知道在运行时添加值的可能方法,但在我看来,下面的解决方案很糟糕,因为我丢失了编译时检查。

int main()
{
std::vector<MyClass> v;
v.emplace_back(MyClass{0});
v.emplace_back(MyClass{1});
v.emplace_back(MyClass{2});
return 0;
}

我的编译器告诉我STL需要使用我删除的副本构造函数MyClass::MyClass(const MyClass&),但有什么办法可以解决吗?

不,你不能。

initializer_list为您创建了一个隐藏数组,声明为const,大致计算如下:

// pseudo code
const MyClass __arr[3] = { MyClass(1), MyClass(2), MyClass(3) };
std::vector<MyClass> v{ std::initializer_list<MyClass>{ __arr, __arr + 2 } }; 

如果你想避免复制,你必须像你说的那样坚持emplace_back

我已经知道在运行时添加值的可能方法。。。

顺便说一下,您的示例是而不是使用emplace_back:的正确方法

std::vector<MyClass> v;
v.emplace_back(MyClass{0});
v.emplace_back(MyClass{1});
v.emplace_back(MyClass{2});

您仍在创建MyClass,然后将其移动到v,这是使用emplace-ish函数时非常常见的错误。

你真正想做的事情可能如下:

v.reserve(3);
v.emplace_back(0);
v.emplace_back(1);
v.emplace_back(2);

这样可以避免意外地调用move构造函数,并且只在正确的位置构造对象一次,不移动,也不复制

目标是在编译时将我的类添加到std::vector中。

如果要在编译时创建数组,请改用std::arraystd::array正是为此目的而设计的:

std::array<MyClass, 3> v = { 1, 2, 3 };