Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Initializing a vector<char> using string literals

Tags:

c++

c++11

What's correct behavior for following code ?

#include <vector>
#include <iostream>

int main() 
{
  std::vector<char> v = { "y", "z" };  
  std::cout << v[0];

  return 0;
}

This is accepted by Clang but not by GCC and VC++

Is this not an undefined behavior ?

like image 478
P0W Avatar asked Nov 10 '14 05:11

P0W


People also ask

How do you initialize a string literal?

The best way to declare a string literal in your code is to use array notation, like this: char string[] = "I am some sort of interesting string. \n"; This type of declaration is 100 percent okey-doke.

What is char in string literal?

[edit] Syntax 1) character string literal: The type of the literal is char[N], where N is the size of the string in code units of the execution narrow encoding, including the null terminator. Each char element in the array is initialized from the next character in s-char-sequence using the execution character set.


1 Answers

After digging a bit into standards, I found following :

Here, I am trying to initialize vector<char> using two string literals, not two chars. using vector(initializer_list<T>). In this case, vector(initializer_list<char>).

But the type of a string literal is "array of n const char", so the initializer-list constructor is not a match.

This doesn't result in compiler error, since the compiler is able to find another constructor that matches

§13.3.1.7¶1 explains the rules :

"When objects of non-aggregate class type T are list-initialized, overload resolution selects the constructor in two phases:

— Initially, the candidate functions are the initializer-list constructors of the class T and the argument list consists of the initializer list as a single argument [which we have seen didn't match].

— 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."

And the match in this case is :

template <class InputIterator> vector(InputIterator first, InputIterator last)

The type of InputIterator has no info of T in the vector<T>. So even if I'm initializing a vector<char>, the two arguments can be of arbitrary type. The only requirement is that they stick to InputIterator property, which const char[] happens to do.

The constructor believes it has been passed two iterators to the same sequence, but it has actually been passed iterators to two completely different sequences, "y" and "z".

So the result of this program is undefined .

Thanks to chris's comment This is post is exactly same as he mentioned over there. See this

like image 152
P0W Avatar answered Oct 10 '22 11:10

P0W