std::string s1 {"Modern C++", 3} vs std::string s1 {str, 3}


std::string s1 {"Modern C++", 3};

Uses the following constructor:

basic_string( const CharT* s,
          size_type count,
          const Allocator& alloc = Allocator() );

So takes 3 chars to get Mod.

std::string s2 {str, 3};

will use the following constructor:

basic_string( const basic_string& other,
          size_type pos,
          const Allocator& alloc = Allocator() );

So taking the string from position 3 onwards giving : ern C++.

One is calling string(char const*, count), the other string(string const&, pos).

One gets the first 3 characters from a buffer, the other all the characters after the 3rd one.

This is because C++ has raw character buffers and std strings. "this is not a std::string". "this is a std string"s, std::string so_is="this";.

std::string is more than 30 years old, and it was added to the C++ language without sufficient care (unlike the STL, which went through more iterations before being added).

Its interface is honestly too rich, and you can run into stuff like this; multiple overloads that lead to confusing results.

Can anyone explain to me why is that?

That is due to std::string having constructors which it really shouldn't (@ORR explained the details). And it shouldn't have these constructors because:

  1. Their effect is easily achievable using named constructor idioms / std::string methods and existing constructors - at no extra cost (in C++11 at least), and
  2. It is not obvious and trivial to understand how the constructor arguments are used from just looking at the constructor invocation.

This is not the only case in the standard library with such undersirable (IMHO) constructors; std::vector is (in)famous for too much constructor variety and confusing/misleading constructor semantics.

Life lessons:

  • Skimp on constructors; not every commonly-used bunch of values used to construct an object of your class deserve their own constructor;
  • instead, use named constructor idioms.
  • Have your code reviewer or some other less-biased party read an invocation of your constructors, to gauge whether the meaning of each one is obvious enough.