简体   繁体   中英

Simple vector initialization in C++11 returns weird error

Compiling this piece of code:

#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;
}

causes an error

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

While slightly changing the vector initialization line (line 5 in previous code) to (line 5,6 in new code)

#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;
}

Causes it to compile successfully. What gives?

g++ parameter: -std=c++11

For vector , brace-initialisation initialises the vector contents to the contents of the initialiser list, so

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

initialises it to a size of 2, with elements N+2 and 0 . This uses the constructor that takes a single parameter of type std::initializer_list .

Changing the braces to parentheses causes it to instead use the two-argument constructor that specifies the size and initial value for all elements. That's what you want here; although you could leave out the second argument since elements are zero-initialised by default.

List-initialisation for vectors is a way to provide a list of initial elements. It is not the same as providing constructor arguments.

That's because std::vector<T> has a constructor taking std::initializer_list<int> which is the best match when you use {x,y,..,z} :

[C++11: 8.5.4/2]: A constructor is an initializer-list constructor if its first parameter is of type std::initializer_list<E> or reference to possibly cv-qualified std::initializer_list<E> for some type E , and either there are no other parameters or else all other parameters have default arguments (8.3.6). [ Note: Initializer-list constructors are favored over other constructors in list-initialization (13.3.1.7). —end note ] The template std::initializer_list is not predefined; if the header <initializer_list> is not included prior to a use of std::initializer_list — even an implicit use in which the type is not named (7.1.6.4) — the program is ill-formed.

[C++11: 13.3.1.7/1]: When objects of non-aggregate class type T are list-initialized (8.5.4), overload resolution selects the constructor in two phases:

  • Initially, the candidate functions are the initializer-list constructors (8.5.4) of the class T and the argument list consists of the initializer list as a single argument.
  • If no viable initializer-list constructor is found, overload resolution is performed again, where the candidate functions are all the constructors of the class T and the argument list consists of the elements of the initializer list.

So:

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

There are seven elements in this vector.

Likewise:

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

There are two elements in this vector; the first one has value N+2 , and the second has value 0 . Your subsequent looping to N , since N in your case is 10, causes memory corruption.

If you instead write the following:

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

then you use the expected vector constructor, which functions similarly to std::vector::resize .

You're initializing a size-2 vector with brace-initialization (vector has a constructor which accepts std::initializer_list<int> )

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

and afterwards asking for the index 2 ( out-of-range ):

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

你可能想写:

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM