Saya menggunakan Microsoft Visual Studio Community 2019, V16.5.2. Saya ingin menguji inisialisasi daftar
Silakan lihat program tes berikut:
#include <string>
void foo(std::string str) {}
int main() {
foo( {"str1", "str2"} );
return 0;
}
Ini mengkompilasi tanpa kesalahan dan peringatan. Mengapa?
Ini memberikan kesalahan runtime: Expression: Transposed pointer range
Adakah yang bisa menjelaskan apa yang terjadi di sini?
Edit.
Saya membongkar kode dan menjalankannya di 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
Itu crash pada panggilan pertama ke konstruktor?
Jawaban:
std::string
memiliki konstruktor template yang membangun string dari pasangan iterator begin / end. String literal di C ++ berpindah keconst char*
s. Dan pointer adalah iterator. Oleh karena itu, inisialisasi daftar memilih konstruktor pasangan mulai / akhir.Anda mendapat kesalahan runtime karena kedua pointer tidak benar-benar membuat rentang yang valid, yang tidak dapat ditentukan pada waktu kompilasi (umumnya).
sumber
<char const *,0>
. Bisakah seseorang tolong jelaskan ini?template< InputIt > (InputIt first, InputIt last,...)
konstruktor di mana parameter templatiter
adalahconst char*
.... dan ternyata implementasi Anda memiliki parameter integer kedua karena alasan tertentu?std::string
memiliki kelebihan konstruktor dalam bentukdan ini dipanggil karena
"str1"
dan"str2"
meluruh keconst char*
danconst char*
merupakan jenis iterator yang dapat diterima.Anda mendapatkan crash karena "rentang iterator" yang Anda berikan ke fungsi tidak valid.
sumber
Itu menggunakan konstruktor dengan iterators dari std :: string (6.).
Dengan [
InputIt
=const char*
].Maka Anda memiliki UB karena rentang
{"str1", "str2"}
tidak valid.sumber