Reputation: 15277
I am using Microsoft Visual Studio Community 2019, V16.5.2. I want to test list initialization
Please see the following test program:
#include <string>
void foo(std::string str) {}
int main() {
foo( {"str1", "str2"} );
return 0;
}
This compiles without error and warning. Why?
It gives a runtime error: Expression: Transposed pointer range
Can somebody please explain what is happening here?
Edit.
I dissasembled the code and run it in the debugger
foo( {"str1", "str2"} );
00F739A8 sub esp,1Ch
00F739AB mov esi,esp
00F739AD mov dword ptr [ebp-0C8h],esp
00F739B3 lea ecx,[ebp-0D1h]
00F739B9 call std::allocator<char>::allocator<char> (0F7136Bh)
00F739BE push eax
00F739BF push offset string "str2" (0F84DB8h)
00F739C4 push offset string "str1" (0F84E2Ch)
00F739C9 mov ecx,esi
00F739CB call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> ><char const *,0> (0F71569h)
00F739D0 call std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > (0F71843h)
00F739D5 add esp,1Ch
It crashes at the first call to the constructor?
Upvotes: 13
Views: 460
Reputation: 180490
std::string
has a constructor overload in the form of
template< class InputIt >
basic_string( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
and this gets called because "str1"
and "str2"
decay to const char*
's and const char*
is an acceptable iterator type.
You get a crash because the "iterator range" you passed to the function is invalid.
Upvotes: 8
Reputation: 217135
That use the constructor with iterators of std::string (6.).
template< class InputIt >
constexpr basic_string( InputIt first, InputIt last,
const Allocator& alloc = Allocator() );
With [InputIt
= const char*
].
Then you have UB as the range {"str1", "str2"}
is invalid.
Upvotes: 7
Reputation: 473272
std::string
has a template constructor that builds a string from a begin/end iterator pair. String literals in C++ devolve down to const char*
s. And pointers are iterators. Therefore, list initialization picked the begin/end pair constructor.
You got a runtime error because the two pointers do not actually create a valid range, which cannot be determined at compile-time (generally).
Upvotes: 16