【问题标题】:std::vector::insert() stopped working when migrating from MSVC 2013 (C++11) to MSVC 2019 (C++17)从 MSVC 2013 (C++11) 迁移到 MSVC 2019 (C++17) 时,std::vector::insert() 停止工作
【发布时间】:2019-07-13 07:43:03
【问题描述】:

我目前正在从

迁移一个大型代码库
  • Visual Studio 2013 (v120)
  • C++11

  • Visual Studio 2019 (v142)
  • C++17

现在,我的测试在奇怪的地方失败了——我的索引越界崩溃和其他奇怪的行为变化。 挖掘后我注意到以下代码:

#include <iostream>
#include <vector>

int main()
{
    std::vector<std::vector<int>> nestedVector;
    nestedVector.insert(nestedVector.begin(), {});
    std::cout << nestedVector.size() << " elements";
}

在 VS2013 中生成一个单元素向量,但在 VS2019 中生成一个空向量

其他插入方式

nestedVector.insert(nestedVector.begin(), std::vector<int>{});
nestedVector.insert(nestedVector.begin(), std::vector<int>());

在这两种设置中工作并正确添加新元素。这里发生了什么?

【问题讨论】:

  • 有道理,因为insert 有一个过载std::initializer_list(参见this)。我不确定为什么 VS 2013 不使用它。 nestedVector.insert(nestedVector.begin(), {1,2,3}); 之类的东西在 VS 2013 中有效吗?
  • VS 2013 没有实现 C++11 初始化列表。 RTM 版本意外包含 initializer_list 标头,但它不起作用。
  • 很有趣,所以现在我们还看到了单个空向量或空初始化器列表之间的视觉歧义?
  • 不是解释,但你可能想看看emplace
  • @HolyBlackCat 非常有趣的 cmets,其中一个有资格作为答案吗?

标签: c++ visual-studio visual-c++ c++17 msvc14


【解决方案1】:

正如 cmets 中已经提到的,在您的原始程序中,nestedVector.insert(nestedVector.begin(), {}) 的调用选择了重载方法:

iterator insert( const_iterator pos, std::initializer_list<T> ilist );

https://en.cppreference.com/w/cpp/container/vector/insert

由于初始值设定项列表为空,因此实际上没有插入任何内容,并且向量大小最后为零。在所有编译器中都是相同的行为,演示:https://godbolt.org/z/9nnET5ren

显然VS2013并没有实现insert方法的这个重载,所以又调用了一个:

iterator insert( const_iterator pos, const T& value );

在向量中创建一个元素。这是错误的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-27
    • 1970-01-01
    • 2018-12-05
    • 1970-01-01
    • 2020-10-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多