我可以通过元素的完美转发来列表初始化 std::vector 吗?
Can I list-initialize std::vector with perfect forwarding of the elements?
我注意到 aggregate list initialization std::vector 执行 copy initialization当 move 更适用。同时,多个emplace_backs为所欲为。
我只能想出这个写模板函数的不完美方案init_emplace_vector
。不过,它仅适用于 非显式单值 构造函数。
template <typename T, typename... Args>
std::vector<T> init_emplace_vector(Args&&... args)
{
std::vector<T> vec;
vec.reserve(sizeof...(Args)); // by suggestion from user: eerorika
(vec.emplace_back(std::forward<Args>(args)), ...); // C++17
return vec;
}
问题
我真的需要使用 emplace_back 来尽可能高效地初始化 std::vector 吗?
// an integer passed to large is actually the size of the resource
std::vector<large> v_init {
1000, // instance of class "large" is copied
1001, // copied
1002, // copied
};
std::vector<large> v_emplaced;
v_emplaced.emplace_back(1000); // moved
v_emplaced.emplace_back(1001); // moved
v_emplaced.emplace_back(1002); // moved
std::vector<large> v_init_emplace = init_emplace_vector<large>(
1000, // moved
1001, // moved
1002 // moved
);
输出
Class large
产生关于 copies/moves 的信息(下面的实现)所以我的程序的输出是:
- initializer
large copy
large copy
large copy
- emplace_back
large move
large move
large move
- init_emplace_vector
large move
large move
large move
大型class实施
我对 large
的实现只是一个 copyable/movable 类型,其中包含一个在 copy/move 上发出警告的大型资源。
struct large
{
large(std::size_t size) : size(size), data(new int[size]) {}
large(const large& rhs) : size(rhs.size), data(new int[rhs.size])
{
std::copy(rhs.data, rhs.data + rhs.size, data);
std::puts("large copy");
}
large(large&& rhs) noexcept : size(rhs.size), data(rhs.data)
{
rhs.size = 0;
rhs.data = nullptr;
std::puts("large move");
}
large& operator=(large rhs) noexcept
{
std::swap(*this, rhs);
return *this;
}
~large() { delete[] data; }
int* data;
std::size_t size;
};
编辑
通过使用保留,没有复制或移动。仅调用 large::large(std::size_t)
构造函数。真正的位置。
Can I aggregate-initialize std::vector ...
没有。 std::vector
不是聚合,因此不能进行聚合初始化。
您可能指的是列表初始化,在这种情况下:
Can I [list-initialise] std::vector with perfect forwarding of the elements?
没有。列表初始化使用 std::initializer_list
构造函数并 std::initializer_list
复制其参数。
你的 init_emplace_vector
似乎是一个不错的解决方案,尽管它可以通过在放置元素之前保留内存来改进。
我注意到 aggregate list initialization std::vector 执行 copy initialization当 move 更适用。同时,多个emplace_backs为所欲为。
我只能想出这个写模板函数的不完美方案init_emplace_vector
。不过,它仅适用于 非显式单值 构造函数。
template <typename T, typename... Args>
std::vector<T> init_emplace_vector(Args&&... args)
{
std::vector<T> vec;
vec.reserve(sizeof...(Args)); // by suggestion from user: eerorika
(vec.emplace_back(std::forward<Args>(args)), ...); // C++17
return vec;
}
问题
我真的需要使用 emplace_back 来尽可能高效地初始化 std::vector 吗?
// an integer passed to large is actually the size of the resource
std::vector<large> v_init {
1000, // instance of class "large" is copied
1001, // copied
1002, // copied
};
std::vector<large> v_emplaced;
v_emplaced.emplace_back(1000); // moved
v_emplaced.emplace_back(1001); // moved
v_emplaced.emplace_back(1002); // moved
std::vector<large> v_init_emplace = init_emplace_vector<large>(
1000, // moved
1001, // moved
1002 // moved
);
输出
Class large
产生关于 copies/moves 的信息(下面的实现)所以我的程序的输出是:
- initializer
large copy
large copy
large copy
- emplace_back
large move
large move
large move
- init_emplace_vector
large move
large move
large move
大型class实施
我对 large
的实现只是一个 copyable/movable 类型,其中包含一个在 copy/move 上发出警告的大型资源。
struct large
{
large(std::size_t size) : size(size), data(new int[size]) {}
large(const large& rhs) : size(rhs.size), data(new int[rhs.size])
{
std::copy(rhs.data, rhs.data + rhs.size, data);
std::puts("large copy");
}
large(large&& rhs) noexcept : size(rhs.size), data(rhs.data)
{
rhs.size = 0;
rhs.data = nullptr;
std::puts("large move");
}
large& operator=(large rhs) noexcept
{
std::swap(*this, rhs);
return *this;
}
~large() { delete[] data; }
int* data;
std::size_t size;
};
编辑
通过使用保留,没有复制或移动。仅调用 large::large(std::size_t)
构造函数。真正的位置。
Can I aggregate-initialize std::vector ...
没有。 std::vector
不是聚合,因此不能进行聚合初始化。
您可能指的是列表初始化,在这种情况下:
Can I [list-initialise] std::vector with perfect forwarding of the elements?
没有。列表初始化使用 std::initializer_list
构造函数并 std::initializer_list
复制其参数。
你的 init_emplace_vector
似乎是一个不错的解决方案,尽管它可以通过在放置元素之前保留内存来改进。