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

问题描述 投票:0回答:1

下面是我用删除的副本构造函数和副本赋值运算符定义的类。这是唯一必须做的假设。

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 :: vector。

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;
}
c++ vector c++17 copy-constructor move-semantics
1个回答
4
投票

我的编译器告诉我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 } }; 

[如果要避免复制,则必须按照您所说的那样坚持[C0​​]。

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

顺便说一句,您给出的示例是not使用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 -ish函数时是一个很常见的错误。

您真正想要做的可能是:

emplace

这样,您就避免了[[偶然地调用move构造函数,而只是在正确的位置构造对象只有一次,没有任何动作,并且没有副本。

目标是在编译时将我的类添加到v.reserve(3); v.emplace_back(0); v.emplace_back(1); v.emplace_back(2);

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

std::array

© www.soinside.com 2019 - 2024. All rights reserved.