考虑以下代码
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
然后我比较emplace_back
和VS2013
之间GCC
的实施
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)...);
}
_Reserve(1);
似乎使用了奇怪的VS2013
。为什么呢?
编辑:
hex
的{{1}}值为-17891602
,表示
Microsoft使用调试HeapFree()来标记释放的堆内存
然后我逐行调试了上述代码,发现0xFEEEFEEE
引起的0XFEEEFEEE
被调用。
答案 0 :(得分:12)
将元素放入包含该元素的向量时,这是VS2013和VS2015中的问题。如果向量调整大小,则对要插入的元素的引用无效。解决方法是在insert中创建元素的副本,然后插入该元素。
auto n = nums[0];
nums.emplace_back(n);
_Reserve调用用于确保为向量分配了一些内存(因此在以后的操作中不必检查它)。
答案 1 :(得分:2)
绑定到
function loadi(srce){ return loadImage(srce); } function loadImage(src) { return new Promise(function(resolve, reject) { $img1.attr('src',src).on('load',function(error){ resolve(); }); // Run image loading logic here // Call resolve() when loading complete, or reject() when fails. }); } loadImage('1.png') .then(loadi('2.png')) .then(loadi('3.png')) .then(function() { console.log('Load successful!'); }) // Not in loadImage(). .catch(function(err) { console.log("Error");/* Handle potential errors */ });
成员函数的函数参数包的对象不是容器元素的元素或子对象。
在 emplace
下的emplace_back()
函数中调用emplace()
。
<击> 撞击>
<击>VS2013
击> <击> 撞击>
我找到了一个好的post,其中描述了 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);
}
下emplace_back()
实施的一些细节。
VS2013
类有不同的实例成员(常规和内部),其中包括以下内容:
std::vector
- 指向数据数组的开头_Myfirst
- 指向数据数组中的第一个未初始化元素。如果等于_Myend,则下一次插入将导致重新分配。你可以通过_Mylast
来电end()
- 指向数据数组的末尾因此,就内存地址而言,会发生以下不等式:
_Myend
查看其中包含_Myfirst <=<= _Mylast <=<= _Myend
的行?这个函数调用导致我们的bug显露出来。
让我们一步一步地工作(参考前面的示例函数)。
_Reserve(1)
首先我们得到一个引用,因为nums.emplace_back(nums[0]);
会返回operator[]
reference
然后我们进入reference operator[](size_type _Pos)
{ ... }
方法,将新的有效引用传递给我们要插入的项目。我们在开始时立即看到的是检查向量的大小超过。只要我们的插入导致向量增加其大小,我们就会在重新分配发生后立即使引用失效。这就是这种有趣但是预期(一旦我们开始实施)行为的原因。