2016-05-15 20 views
6

Dlaczego poniższy kod się kompiluje? Kompiluje się i działa dobrze z klang i wydrukami. first. Uważam jednak, że prawidłowe zachowanie powinno polegać na skargach i wydawaniu prawidłowego błędu.C++ Niepoprawne zachowanie inicjalizacji std :: string

#include <iostream> 
#include <string> 

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

To pytanie powstało pod inspiracją this.

+0

Dzieje się tak dlatego, że "pierwszy" ciąg ma niejawne "\ 0" na końcu .... które powoduje, że obiekt 'string' przestaje szukać więcej znaków (mimo że prawdopodobnie nadal przydziela pełne pamięć "drugiego" do) – DarthRubik

+1

@DarthRubik: Nie. To nie jest to, co się dzieje. –

+0

Podstawowy problem jest taki sam jak [to pytanie] (https://stackoverflow.com/questions/24112281/c11-initializer-list-fails- but-only-on- list-- length-2). – chris

Odpowiedz

9

std::string ma konstruktor szablonu, który pobiera dwa iteratory. Po przejściu przez literały łańcuchowe ulegną one zniszczeniu do char const*, co kwalifikuje się jako iterator. Ponieważ jednak wskaźniki te nie stanowią prawidłowego zakresu, masz niezdefiniowane zachowanie.

+0

To jest błąd w klangu; czy to jest poprawne? –

+0

@EissaN. Nie. To błąd w twoim kodzie. Twój program wykazuje niezdefiniowane zachowanie, a zatem clang nie jest zobowiązany do robienia czegokolwiek szczególnego i może, o ile chodzi o standard C++, zrobić cokolwiek w ogóle. –

4

To jest niezdefiniowane zachowanie.

Jest to wywołanie konstruktora z std::string, który przyjmuje dwa iteratory, początkową i końcową wartość iteratora. Ponieważ oba parametry inicjalizacji mają ten sam typ, są interpretowane jako para iteratorów i pasują do tego konkretnego przeciążonego konstruktora.

Wartości wskaźników znaków są interpretowane jako początkowe/końcowe wartości iteratora. Zdarza się, że działa z klangiem, ale z gcc powoduje to wyjątek.