Liste Başlatma Kopyalansın mı? Bu neden derleniyor?


13

Microsoft Visual Studio Community 2019, V16.5.2 kullanıyorum. Liste başlatmayı test etmek istiyorum

Lütfen aşağıdaki test programına bakın:

#include <string>

void foo(std::string str) {}

int main() {

    foo( {"str1", "str2"} );

    return 0;
}

Bu hata ve uyarı olmadan derlenir. Neden?

Bir çalışma zamanı hatası verir: Expression: Transposed pointer range

Birisi burada neler olduğunu açıklayabilir mi?


Düzenle.

Kodu söktüm ve hata ayıklayıcıda çalıştırdım

    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  

Yapıcıya ilk çağrıda çöküyor mu?


Düzenlemenizi anlamıyorum, ama belki farklı bir soru gibi görünüyor, bu yüzden belki yeni bir soru göndermeniz gerekiyor?
Mooing Duck

Yanıtlar:


16

std::stringbaşlangıç ​​/ bitiş yineleyici çiftinden bir dize oluşturan bir şablon yapıcısına sahiptir. C ++ 'da dize değişmez değerleri const char*s'ye dönüşür . Ve işaretçiler yineleyicilerdir. Bu nedenle, liste başlatma başlangıç ​​/ bitiş çifti yapıcısını seçti.

İki işaretçi, derleme zamanında (genellikle) belirlenemeyen geçerli bir aralık oluşturmadığından bir çalışma zamanı hatası aldınız.


Anlıyorum. Aralık yapıcısı. Kodu söküp hata ayıkladım. Yapıcıya ilk çağrıda çöküyor. Anlamıyorum <char const *,0>. Birisi lütfen bunu açıklayabilir mi?
Armin Montigny

Demek ki o aradığını template< InputIt > (InputIt first, InputIt last,...)şablon parametresi yapıcısı iterolduğunu const char*.... ve görünüşte senin uygulaması nedense ikinci tamsayı parametresi vardır?
Mooing Duck

@ArminMontigny: Ne olduğunu açıkla? Sökme esasen önemsizdir. Kodunuzun sözdizimsel olarak geçerli olduğu belirtiliyor, ancak geçerli bir yineleyici aralığını geçmemesi nedeniyle tanımlanmamış davranış veriyor. Kodunuzun neden işlevsel olmadığını anlamak için sökme işlemini anlamanız gerekmez.
Nicol Bolas

8

std::string şeklinde bir yapıcı aşırı yüke sahiptir

template< class InputIt >
basic_string( InputIt first, InputIt last,
              const Allocator& alloc = Allocator() );

ve bunun nedeni çağrılan "str1"ve "str2"çürümeye const char*'in ve const char*kabul edilebilir bir yineleyici türüdür.

İşleve ilettiğiniz "yineleyici aralığı" geçersiz olduğundan bir kilitlenme yaşarsınız.


Teşekkürler, anlaşıldı. +1. Lütfen düzenlemeye bakın.
Armin Montigny

7

Yapıcıyı std :: string (6.) yineleyicileri ile kullanır .

template< class InputIt >
constexpr basic_string( InputIt first, InputIt last,
                        const Allocator& alloc = Allocator() );

[ InputIt= const char*] İle .

Sonra aralık {"str1", "str2"}geçersiz olduğundan UB var .


Teşekkürler, anlaşıldı. +1. Lütfen düzenlemeye bakın.
Armin Montigny
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.