6

Why does the following code compile? It compiles and runs fine with clang and prints first. But, I believe the correct behavior should be to complain and issue a proper error.

#include <iostream>
#include <string>

int main()
{
    std::string s{ "first", "second" };
    std::cout << s << std::endl;
}

This question is inspired by this.

Community
  • 1
  • 1
Eissa N.
  • 1,695
  • 11
  • 18
  • It is because the "first" string has an implicit "\0" at the end of it....that tells the `string` object to stop looking for more chars (even though it probably is still allocating the full memory of the "second" to) – DarthRubik May 15 '16 at 02:37
  • 1
    @DarthRubik: No. That's not what's happening. – Benjamin Lindley May 15 '16 at 02:48
  • The underlying problem is the same as [this question](https://stackoverflow.com/questions/24112281/c11-initializer-list-fails-but-only-on-lists-of-length-2). – chris May 15 '16 at 02:52

2 Answers2

8

std::string has a template constructor that takes two iterators. When you pass string literals, they will decay to char const*, which qualifies as an iterator. However, since those pointers do not form a valid range, you have undefined behavior.

Benjamin Lindley
  • 101,917
  • 9
  • 204
  • 274
  • @EissaN. No. It's a bug in your code. Your program exhibits undefined behavior, and therefore clang is under no obligation to do anything in particular, and can, as far as the C++ standard is concerned, do anything at all. – Benjamin Lindley May 16 '16 at 22:10
4

This is undefined behavior.

This is invoking a constructor of std::string that accepts two iterators, the beginning and the ending iterator value. Because both initialization parameters have the same type, they are interpreted as a pair of iterators, and match this particular overloaded constructor.

The values of the character pointers are interpreted as beginning/ending iterator values. It just happens to work with clang, but with gcc this throws an exception.

Sam Varshavchik
  • 114,536
  • 5
  • 94
  • 148