为什么使用 emplace_back 和删除的复制构造函数不起作用?

Why doesn't this use of emplace_back with deleted copy constructor work?

我有一个类型,我已经从中删除了复制构造函数,我想要一个这种类型的 vector,所以我需要通过 emplace_back 创建所有元素。但是,emplace_back 似乎需要一个复制构造函数,因为编译器会警告无法实例化 emplace_back,因为复制构造函数已被删除。为什么需要拷贝构造函数?我认为 emplace_back 的重点是在不复制任何内容的情况下构建 vector。我什至可以拥有 vector 个没有复制构造函数的对象吗?

class MyType {
public:
    MyType(std::array<double, 6> a) {}
    MyType(const MyType& that) = delete;
};

int main() {
    std::vector<MyType> v;
    std::array<double, 6> a = {1,2,3,4,5,6};
    v.emplace_back(a);
}

编译器是 clang/llvm.

vector的内部存储增长时,它需要将元素从旧存储移动到新存储。 By deleting the copy constructor, you also prevent it generating the default move constructor.

为了能够调用 emplace_back,您的类型应该是 EmplaceConstructible or MoveInsertible。 如果删除了复制构造函数,则需要为 class 提供一个移动构造函数。 (检查 this 以了解 emplace_back 的要求)

 MyType(MyType &&a) {/*code*/} //move constructor

如果您尝试 运行 此代码:

// Example program
#include <iostream>
#include <string>
#include <array>
#include <vector>
class MyType {
public:
    MyType(std::array<double, 6> a) {
        std::cout<< "constructed from array\n";
        }
    MyType(const MyType& that){
          std::cout<< "copy\n";
    }

    MyType(MyType&& that){
          std::cout<< "move\n";
    }
};

int main() {
    std::vector<MyType> v;
    std::array<double, 6> a = {1,2,3,4,5,6};
    v.emplace_back(a);
}

您将得到以下结果:

constructed from array

Live Demo

很明显,只调用了 std::Array 中的 constructor。所以,不需要copy constructor。但同时如果你 deleted copy constructor,编译器将引发错误(至少在我试过的两个编译器上 first second )。我认为有些编译器会在使用 emplace_back 时检查 copy constructor 是否存在,即使在这种实际情况下没有必要,而其他编译器则不会。我不知道这里的标准是什么(哪个编译器是对的还是错的)。