使用默认构造函数在向量中进行安装

Chi*_*y C 6 c++ vector c++11 emplace

我想使用vector::emplace默认构造一个不可复制不可赋值的对象,然后使用迭代器对该对象使用特定的方法来创建新创建的对象.请注意,类的参数化构造函数只是默认构造函数.一个简单的例子是:

#include <iostream>
#include <vector>
using namespace std;

class Test {
public:
    Test() {}
private:
    Test(const Test&) = delete;             // To make clas un-copyable.
    Test& operator=(const Test&) = delete;

    int a_;
};

int main() {
    vector<Test> test_vec;
    test_vec.emplace_back();     // <---- fails

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

vector::emplace()构造一个新对象,但需要一个非默认构造函数的参数.vector::emplace_back()将在向量的末尾构造.

有没有办法安置默认构造.有没有办法使用分段构造或默认转发可能使用std::piecewise_construct地图?例如,在地图的情况下,我们可以使用:

std::map<int,Test> obj_map;
int val = 10;
obj_map.emplace(std::piecewise_construct,
                std::forward_as_tuple(val),
                std::forward_as_tuple());
Run Code Online (Sandbox Code Playgroud)

矢量有类似的东西吗?

Chi*_*y C 8

正如 @dyp 和 @Casey 在评论中指出的那样,std::emplace不适用于 Test 类的向量,因为该类既不可移动也不可复制,因为“用户声明的复制构造函数会抑制默认移动构造函数的生成”(@Casey) 。

要在这里使用emplace,类需要可移动或可复制。我们可以通过显式定义(和默认)移动构造函数来使类可移动:

public:
    Test(Test&& other) = default;
    Test& operator=(Test&& other) = default;
Run Code Online (Sandbox Code Playgroud)

这也将隐式地使该类不可复制,“因为声明移动操作将抑制副本的隐式生成”。(@凯西)

现在我们可以使用std::emplace_back()然后使用vector::back()来调用新创建的对象的方法。


Col*_*mbo 7

vector::emplace_back() 将在向量的末尾构造,但也需要参数.

参数包可以为空.因此,emplace_back可以不带参数调用可变参数模板; 即

vector<VeryLimitedClass> vec;
vec.emplace_back();
Run Code Online (Sandbox Code Playgroud)

VeryLimitedClass通过其默认构造函数初始化类型对象的有效代码,并在后面"展开"它vec.

  • 我们可以肯定地说默认分配器将根据[allocator.members]/12执行值初始化,它表示`construct(U*p,Args && ... args)`的效果相当于`:: new( (void*)p)U(std :: forward <Args>(args)...)`.但是我们不能肯定地说默认分配器在没有看到整个翻译单元的情况下使用,即使知道向量的类型是`std :: vector <VeryLimitedClass>`,因为`std :: allocator <VeryLimitedClass>`可以是用户定义的专业化. (4认同)