此代码在Ideone上按预期编译并运行 :
#include <iostream>
#include <string>
#include <vector>
int main() {
std::vector<std::wstring> strVec;
strVec.insert(strVec.end(), { L"black", L"white", L"red" });
strVec.insert(strVec.end(), { L"blue", L"green" }); // STL exception
for (auto &i : strVec) {
std::wcout << i << " ";
}
return 0;
}
然而,MSVC(Visual Studio 2013)中的“无效迭代器范围”失败。有任何见解吗?
BTW,插入更多元素,例如,在第二个插入,这适用于MSVC:strVec.insert( strVec.end(), { L"blue", L"green", L"yellow" } );
与容量/大小相关并使某些迭代器无效?但是第二个insert
请求新的迭代器end()
,它必须是有效的,对吗?或者......它实际上是关于初始化列表?
注意:不在这里寻找变通方法(大量的) - 只是试图弄清楚这是否是特定于MSVC的错误或者是否存在合法错误...
答案 0 :(得分:2)
VS 2013选择了重载vector<T>::insert(const_iterator, const T&)
,从一对指针wstring
构建const wchar*, const wchar*
,将其解释为一系列字符的开头和结尾;请注意,宽字符串文字会衰减为const wchar*
指针。这就是为什么只有在尝试精确插入2个元素时才会出现问题。
这是调用堆栈:
msvcp120d.dll!std::_Debug_message(const wchar_t * message, const wchar_t * file, unsigned int line) Line 15 C++
Project1.exe!std::_Debug_range2<wchar_t const *>(const wchar_t * _First, const wchar_t * _Last, const wchar_t * _File, unsigned int _Line, std::random_access_iterator_tag __formal) Line 576 C++
Project1.exe!std::_Debug_range<wchar_t const *>(const wchar_t * _First, const wchar_t * _Last, const wchar_t * _File, unsigned int _Line) Line 584 C++
Project1.exe!std::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >::basic_string<wchar_t,std::char_traits<wchar_t>,std::allocator<wchar_t> >(const wchar_t * _First, const wchar_t * _Last) Line 860 C++
Project1.exe!main() Line 9 C++
VS 2013是错误的,因为[over.ics.rank]:
3 - [...]
- 列表初始化序列
L1
是一个比列表初始化序列L2
更好的转换序列,如果:
L1
转化为std::initializer_list<X>
代表某些X
而L2
则不会[...]
这已在VS2015中修复。
答案 1 :(得分:1)
可能会发生这种情况,因为当您编写{ L"blue", L"green" }
编译器时,将它们用作构造值(std::wstring
)的两个指针并将其传递给下一个std::vector::insert
重载:
insert( const_iterator pos, const T& value );
因此,从指针L"blue"
到L"green"
的运行可能会在程序无权读取的地方结束,或者它检查第一个指针是否小于秒当他们没有时抛出异常。