Vio*_*ffe 11 c++ vector stdvector c++11
我有一个可复制构造的结构向量,但不可赋值:
struct Struct
{
inline Struct(const std::string& text, int n) : _text(text), _n(n) {}
inline Struct(const Struct& other) : _text(other._text), _n(other._n) {}
const std::string _text;
const int _n;
Struct& operator=(const Struct&) = delete;
};
Run Code Online (Sandbox Code Playgroud)
一切都很好.事实上,我甚std::vector<Struct>至可以将值作为函数的返回值传递.然而,这失败了:
std::vector<TextFragment> v1, v2;
v2 = v1;
Run Code Online (Sandbox Code Playgroud)
当然,错误是:
错误:C2280:'Struct&Struct :: operator =(const Struct&)':尝试引用已删除的函数
我不明白为什么它试图调用它.这是否是某种优化以避免重新分配向量的内存块?
这是为了避免重新分配向量的内存块的某种优化吗?...
几乎。这是一种优化,可以避免重新分配vector's 中可能存在的任何内存块value_type。也就是说,这是一个全局假设,即赋值比销毁后复制构造更有效。
例如,考虑vector<string>分配,对于两个相同大小的vectors,以及string中每个点的一堆相同大小的s vector:
v2 = v1;
Run Code Online (Sandbox Code Playgroud)
所有这些操作所要做的就是memcpy每个string. 根本没有分配。减少分配/解除分配是当今存在的最重要的优化之一。
但是,您的Struct. 您想要做的是指示vector您不想分配您的Structs,而是销毁它们,然后从v1. 这样做的语法是:
v2.clear();
for (const auto& x : v1)
v2.push_back(x);
Run Code Online (Sandbox Code Playgroud)
正如下面的评论中所指出的,您还可以复制构造v1,然后swap复制。您要么需要创建 的临时本地副本v1,要么需要v1在成员交换的“lhs”上使用:
std::vector<Struct>(v1).swap(v2);
Run Code Online (Sandbox Code Playgroud)
我个人觉得这很难阅读。在 C++11/14 中,我更喜欢这种涉及移动分配的替代方案:
v2 = std::vector<Struct>(v1);
Run Code Online (Sandbox Code Playgroud)
这些替代品在眼睛上更容易。但是第一种选择,使用clear()和push_back平均而言将是最有效的。这是因为第一个选择是唯一有机会capacity()在v2. 另外两个总是capacity()在副本中重新创建新的v1并丢弃v2现有的capacity()。