我试图了解以下行为:
#include <vector>
#include <iterator>
struct Foo {
Foo(int a) : a_ {a} {}
const int a_; // Note the const
};
int main(int argc, char **argv) {
std::vector<Foo> v1 {Foo {0}};
std::vector<Foo> v2 {Foo {1}};
auto first = std::begin(v2);
auto last = std::end(v2);
for (; first != last; ++first) {
v1.push_back(*first); // Fine
}
//v1.insert(v1.begin(), first, last); // Does not compile
return 0;
}
Run Code Online (Sandbox Code Playgroud)
事实证明,该const成员Foo隐含地删除了使用Foo的副本赋值运算符std::vector::insert.
为什么std::vector::insert需要在std::vector::push_back复制构造时复制赋值?这是否意味着手动连接两个向量可能更有效?这是使用LLVM.
小智 6
从逻辑上讲,没有理由要求赋值运算符.该insert操作可以完全通过移动任何现有元素vec[x]来实现,vec[x+1]通过使用(大致)vec[x+1].~T(); new(&vec[x+1]) T(std::move(vec[x]));循环来销毁现有元素,并使用就地构造来向前移动前一个元素.
然而,一种更自然的写入方法,在精心设计的类中通常至少同样有效,如果不是更有效,则使用赋值:vec[x+1] = std::move(vec[x]);.一个简单的例子,它可以提高效率,如果向量元素的构造和破坏涉及分配和释放内存:使用赋值可以轻松绕过它.
做出了一个决定,允许向量使用赋值运算符比缺点有更多的好处.你的课很不寻常,你的课不会从这个决定中受益.这很不幸,但是没有办法设计出适合每个用例的矢量.
| 归档时间: |
|
| 查看次数: |
1102 次 |
| 最近记录: |