C ++ 11中的简单向量初始化会返回奇怪的错误

时间:2014-10-17 13:34:15

标签: c++ c++11 vector g++

编译这段代码:

#include <vector>

long long sumOfMedians(int seed, int mul, int add, int N, int K)
{
  std::vector<int> nos{N+2,0};
  for(int i=0; i<N; i++)
    {
      if(i == 0)
    nos[i] = seed;
      else
    nos[i] = (nos[i-1]*mul + add)%65536;
    }
}

int main()
{
  sumOfMedians(3,1,1,10,3);
  return 0;
}

导致错误

*** Error in `./a.out': free(): invalid next size (fast): 0x00000000006e8010 ***
[2]    31743 abort (core dumped)  ./a.out

稍微改变矢量初始化线(前一代码中的第5行)到(新代码中的第5,6行)

#include <vector>

long long sumOfMedians(int seed, int mul, int add, int N, int K)
{
  std::vector<int> nos;
  nos.resize(N+2,0);
  for(int i=0; i<N; i++)
    {
      if(i == 0)
    nos[i] = seed;
      else
    nos[i] = (nos[i-1]*mul + add)%65536;
    }
}

int main()
{
  sumOfMedians(3,1,1,10,3);
  return 0;
}

使其成功编译。是什么给了什么?

g ++参数:-std = c ++ 11

4 个答案:

答案 0 :(得分:6)

对于vector,大括号初始化将向量内容初始化为初始化列表的内容,所以

std::vector<int> nos{N+2,0};

将其初始化为大小为2,包含元素N+20。这使用了带有std::initializer_list类型的单个参数的构造函数。

将大括号更改为括号会导致它改为使用双参数构造函数来指定所有元素的大小和初始值。这就是你想要的;虽然你可以省略第二个参数,因为默认情况下元素是零初始化的。

答案 1 :(得分:6)

向量的列表初始化是一种提供初始元素列表的方法。 与提供构造函数参数相同。

这是因为使用{x,y,..,z}std::vector<T> has a constructor taking std::initializer_list<int>是最佳匹配:

  

[C++11: 8.5.4/2]:构造函数是初始化列表构造函数,如果它的第一个参数是std::initializer_list<E>类型,或者对某些类型可能是cv-qualified std::initializer_list<E>的引用E,并且没有其他参数,或者所有其他参数都有默认参数(8.3.6)。 [注意: 初始化列表构造函数优于列表初始化中的其他构造函数(13.3.1.7)。 -end note] 模板{ {1}}未预定义;如果在使用std::initializer_list之前未包含标题<initializer_list> - 即使是未命名类型的隐式用法(7.1.6.4) - 程序也是格式错误。

     

std::initializer_list当非聚合类类型[C++11: 13.3.1.7/1]:的对象被列表初始化(8.5.4)时,重载决策分两个阶段选择构造函数:

     
      
  • 最初,候选函数是类T的初始化列表构造函数(8.5.4),参数列表由初始化列表作为单个参数组成。
  •   
  • 如果找不到可行的初始化列表构造函数,则再次执行重载解析,其中候选函数是类T的所有构造函数,参数列表由初始化列表的元素组成。
  •   

所以:

T

此向量中有七个元素。

同样地:

std::vector<int> v{1,2,3,4,5,6,7};

此向量中有两个元素;第一个值为std::vector<int> nos{N+2, 0}; ,第二个值为N+2。您的后续循环0,因为您的案例中的N为10,会导致内存损坏。

如果您改为编写以下内容:

N

然后使用预期的向量构造函数,其功能类似于std::vector<int> nos(N+2, 0);

答案 2 :(得分:1)

您正在使用brace-initialization初始化 size-2 vector (vector有一个接受std::initializer_list<int>的构造函数)

std::vector<int> nos{ N + 2, 0 };

然后询问索引2(超出范围):

nos[2] = (nos[2 - 1] * mul + add) % 65536;

答案 3 :(得分:0)

你可能想写:

  std::vector<int> nos(N+2,0);