将initializer_list插入std :: vector时“无效的迭代器范围”

时间:2016-04-11 19:50:51

标签: c++ vector stl

此代码在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的错误或者是否存在合法错误...

2 个答案:

答案 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>代表某些XL2则不会[...]
    •   
  •   

这已在VS2015中修复。

答案 1 :(得分:1)

可能会发生这种情况,因为当您编写{ L"blue", L"green" }编译器时,将它们用作构造值(std::wstring)的两个指针并将其传递给下一个std::vector::insert重载:

insert( const_iterator pos, const T& value ); 

因此,从指针L"blue"L"green"的运行可能会在程序无权读取的地方结束,或者它检查第一个指针是否小于秒当他们没有时抛出异常。