10

我想使用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;
}

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());

向量有类似的东西吗?

4

3 回答 3

9

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

参数包可以为空。emplace_back因此可以不带参数调用可变参数模板;IE

vector<VeryLimitedClass> vec;
vec.emplace_back();

是通过其默认构造函数初始化类型对象VeryLimitedClass并将其“放置”在vec.

于 2014-11-21T18:45:52.700 回答
6

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

emplace在此处使用,该类需要是可移动的。我们可以通过显式定义(和默认)移动构造函数来做到这一点:

public:
    Test(Test&& other) = default;
    Test& operator=(Test&& other) = default;

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

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

于 2014-11-21T19:45:31.407 回答
0

对于map,简单:

std::map<int, Object> obj_map;
obj_map[10]; // default-constructs an object with key 10

否则,您所拥有的也可以:

obj_map.emplace(std::piecewise_construct,
                std::forward_as_tuple(10),
                std::forward_as_tuple(args, to, construct, with));

[编辑] 的等价物vectoremplace_back

obj_vector.emplace_back(); // default construct
obj_vector.emplace_back(args, to, std::move(construct), with); // forward these
于 2014-11-21T18:31:28.267 回答