vector<int> v;
v.push_back(1);
v.push_back(v[0]);
Run Code Online (Sandbox Code Playgroud)
如果第二个push_back导致重新分配,则向量中对第一个整数的引用将不再有效.那么这不安全吗?
vector<int> v;
v.push_back(1);
v.reserve(v.size() + 1);
v.push_back(v[0]);
Run Code Online (Sandbox Code Playgroud)
这样可以安全吗?
使用push_back时std::vector,我可以推送向量本身的元素,而不必担心因重新分配而使参数无效:
std::vector<std::string> v = { "a", "b" };
v.push_back(v[0]); // This is ok even if v.capacity() == 2 before this call.
Run Code Online (Sandbox Code Playgroud)
但是,在使用时emplace_back,std::vector将参数转发给构造函数,std::string以便复制构造在向量中发生.这使我怀疑向量的重新分配在新字符串被复制构造之前发生(否则它不会被分配到位),从而在使用之前使参数无效.
这是否意味着我无法添加向量本身的元素emplace_back,或者在重新分配的情况下是否有某种保证,类似于push_back?
在代码中:
std::vector<std::string> v = { "a", "b" };
v.emplace_back(v[0]); // Is this valid, even if v.capacity() == 2 before this call?
Run Code Online (Sandbox Code Playgroud) 考虑以下insert和emplace成员函数std::vector<T>:
template <class... Args> iterator emplace(const_iterator position, Args&&... args);
iterator insert(const_iterator position, const T& x);
iterator insert(const_iterator position, T&& x);
iterator insert(const_iterator position, size_type n, const T& x);
Run Code Online (Sandbox Code Playgroud)
如果通过引用向量本身的元素作为参数来调用其中一个,该怎么办?通常,它们中的每一个都会使对所有元素的引用无效,这些元素position可能包括参数,或者如果发生重新分配,则引用所有元素,这肯定包含它,但这是否意味着这样的调用无效或插入(似乎先发生?
查看一些常见的实现会产生奇怪的结果:
libstdc ++在移动任何元素之前复制参数,但仅在const T&重载中insert.它包含这个评论:
这三个操作的顺序由C++ 0x情况决定,其中移动可以改变属于现有向量的新元素.这只是调用者通过const lvalue ref获取元素的问题(见23.1/13).
但是C++11§23.1只是容器库的简短摘要,即使我们假设这是指§23.2.1(以前是C++ 03中的§23.1),仅仅是§23.2.1/ 13给出了分配器感知容器的定义,这似乎与此无关.我已经看了第23章,但我没有找到任何相关的东西.
libc ++在移动任何元素之前创建一个临时元素emplace,而在insert其中首先移动元素但将参数引用转换为指针并调整它以确保它指向原始元素 - 但同样,它仅在const T&重载中完成所有这些操作.
在所有情况下移动任何元素之前,Visual C++会创建一个副本/临时文件.
我错过了标准定义此行为的地方吗?为什么我看到的三个C++库彼此不一致?为什么libstdc ++评论说它只是一个问题insert(const_iterator, const T&)?如果标准不要求这个工作,为什么图书馆总是懒得让它工作呢?(当然这会花费一些本来可以避免的副本和/或移动.)最后,如果我正在实现一个类似的容器,std::vector我应该让它工作吗?