为什么这种将emplace_back与已删除的复制构造函数一起使用不起作用?

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

本文关键字:构造函数 复制 一起 不起作用 删除 emplace back 为什么      更新时间:2023-10-16

我有一个类型,我已经从中删除了复制构造函数,我希望有一个这种类型的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/lilvm。

vector的内部存储增长时,它将需要将元素从旧存储移动到新存储。通过删除复制构造函数,还可以防止它生成默认的移动构造函数。

要能够调用template_back,您的类型应该是EmplaceConstructable或MoveInsertable。如果已经删除了复制构造函数,则需要为类提供一个move构造函数。(检查此项以了解template_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 arrayn";
        }
    MyType(const MyType& that){
          std::cout<< "copyn";
    }
    MyType(MyType&& that){
          std::cout<< "moven";
    }
};
int main() {
    std::vector<MyType> v;
    std::array<double, 6> a = {1,2,3,4,5,6};
    v.emplace_back(a);
}

您将得到以下结果:

由阵列构建

实时演示

很明显,仅调用来自std::Arrayconstructor。因此,不需要copy constructor。但同时,如果deletedcopy constructor,编译器将引发错误(至少在我前一秒尝试的两个编译器上)。我认为一些编译器在使用template_back时会检查copy constructor的存在,即使在这种实际情况下没有必要,而其他编译器则不会。我不知道这里的标准是什么(哪个编译器是对的还是错的)。