emplace_back() issue under VS2013
emplace_back() issue under VS2013
考虑以下代码
std::vector<int> nums{21, 22, 23, 24};
nums.emplace_back(nums[0]);
nums.emplace_back(nums[1]);
for (auto n : nums) {
std::cout << n << std::endl;
}
VS2013
输出
21
22
23
24
-17891602
22
为什么-17891602
在这里
GCC 4.8.4
的输出正确,如下所示
21
22
23
24
21
22
然后比较了VS2013
和GCC
对emplace_back
的实现
VS2013
template<class... _Valty>
void emplace_back(_Valty&&... _Val)
{ // insert by moving into element at end
if (this->_Mylast == this->_Myend)
_Reserve(1);
_Orphan_range(this->_Mylast, this->_Mylast);
this->_Getal().construct(this->_Mylast,
_STD forward<_Valty>(_Val)...);
++this->_Mylast;
}
GCC-
template<typename _Tp, typename _Alloc>
template<typename... _Args>
void
vector<_Tp, _Alloc>::
emplace_back(_Args&&... __args)
{
if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage)
{
_Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish,
std::forward<_Args>(__args)...);
++this->_M_impl._M_finish;
}
else
_M_emplace_back_aux(std::forward<_Args>(__args)...);
}
在VS2013
中似乎使用了奇怪的_Reserve(1);
。为什么?
编辑:
-17891602
的hex
值为0xFEEEFEEE
,表示
由Microsoft的调试HeapFree()用于标记已释放的堆内存
参考幻数
然后我逐行调试了上面的代码,发现_Reserve(1);
引起的0XFEEEFEEE
被调用了。
在VS2013和VS2015中将元素放置到包含该元素的向量中时,这是一个问题。如果向量大小调整,则对插入的元素的引用无效。解决方法是在insert中创建元素的副本,然后插入该副本。
auto n = nums[0];
nums.emplace_back(n);
_Reserve调用用于确保为向量分配了一些内存(因此在以后的操作中不必检查它)。
模板问题
绑定到
emplace
成员函数的函数参数包的对象应而不是容器元素的元素或子对象。
emplace_back()
是在VS2013
下的emplace()
函数中调用的
template<class... _Valty>
iterator emplace(const_iterator _Where, _Valty&&... _Val)
{ // insert by moving _Val at _Where
size_type _Off = _VIPTR(_Where) - this->_Myfirst;
#if _ITERATOR_DEBUG_LEVEL == 2
if (size() < _Off)
_DEBUG_ERROR("vector emplace iterator outside range");
#endif /* _ITERATOR_DEBUG_LEVEL == 2 */
emplace_back(_STD forward<_Valty>(_Val)...);
_STD rotate(begin() + _Off, end() - 1, end());
return (begin() + _Off);
}
我发现了一篇很好的帖子,它描述了VS2013
下emplace_back()
实现的一些细节。
std::vector
类具有不同的实例成员(常规和内部),其中包括以下成员:
_Myfirst
-指向数据数组的开头_Mylast
-指向数据数组中第一个未初始化的元素。如果等于_Myend,则下一次插入将导致重新分配。你接到这个家伙的end()
电话_Myend
-指向数据数组的末尾
因此,就存储器地址而言,发生了以下不等式:
_Myfirst <=<= _Mylast <=<= _Myend
看到那行_Reserve(1)
了吗?这个函数调用导致我们的bug暴露出来。
让我们逐步完成(请参阅前面的示例函数)。
nums.emplace_back(nums[0]);
首先,由于operator[]
返回reference
,因此我们获得了对该项目的引用
reference operator[](size_type _Pos)
{ ... }
然后我们进入emplace_back
方法,将新鲜有效的引用传递给要插入的项。我们在开始时立即看到的是对向量大小超出的检查。只要我们的插入导致向量的大小增加,我们就会在重新分配发生后使引用无效。这就是产生如此有趣但又令人期待(一旦我们开始实现)的行为的原因。
- Seg Fault Issue C++ (file IO / getline)
- Issue with WriteProcessMemory
- std::partition segfault issue
- VSCode C/C++ Intellisense issue: Undefined identifiers (Linu
- OpenGL glBufferSubData Offset issue
- boost::property_tree XML issue
- qt QWidget::closeEvent link issue
- QT 和 JIRA Rest API: /rest/api/2/issue/createmeta 意外返回韩语的 iss
- Crypto++ GetModulus() issue
- Vector.push_back Issue
- C++嵌套类从嵌套类继承,请键入 issue
- C++ PBKDF2 Issue
- Cppcheck 静态代码分析器实际上可以检测到不太常见的警告(如 "Relative Path Traversal (CWE-23)" 或"Buffer Under-read(CWE-127)")吗
- CMake FindJNI issue on linux
- 如何使用 C++ 和 Matlab Engine under Kdevelopwith CMakeList.
- C++ 将二维数据库保存到文件ISSUE中
- MySQL with Qt issue
- 数学背后的"compute n! under modulo p"?
- Qt with Visual Studio macro issue
- emplace_back() issue under VS2013