2016-04-13 11 views
3

Dies ist der vereinfachte Code:Constructor, Initialisiererliste und unterschiedliches Verhalten in g ++ und Klirren

#include <vector> 

class VInitList 
{ 
public: 
    explicit VInitList(std::vector<int> v){} 
}; 

int main() 
{ 
    VInitList vil({{}}); 
} 

und Kompilieren mit g ++ 5.2.1 a diesen Fehler:

error: call of overloaded ‘VInitList(<brace-enclosed initializer list>)’ is ambiguous 
    VInitList vil({{}}); 
        ^
main.cpp:6:5: note: candidate: VInitList::VInitList(std::vector<int>) 
    VInitList(std::vector<int> v){} 
    ^
main.cpp:3:7: note: candidate: constexpr VInitList::VInitList(const VInitList&) 
    class VInitList 
     ^
main.cpp:3:7: note: candidate: constexpr VInitList::VInitList(VInitList&&) 

Als ich das sah, Compiler-Fehler Ich habe herausgefunden, dass ich aus Versehen {{}} geschrieben habe (ja, sei nicht gemein zu mir), aber ich kann den Fehler immer noch nicht verstehen. IMHO entweder der Compiler muss die zusätzliche {} loswerden oder einen Syntaxfehler zurückgeben.

Dann habe ich versucht, dies zu kompilieren:

std::vector<int> v = {{{}}}; 

, die wie vorgesehen funktioniert.

+0

Ich habe nur einen Blick auf Ihr Beispiel geworfen, aber Sie haben ein zusätzliches Paar Klammern auf dem Code-Snippet, das kompiliert wurde, vielleicht deshalb? – Henningsson

+0

Es kompiliert nicht in g ++ 5.2.1, aber es ist in Clang 3.7.0 – FrankS101

+0

Interessant Q. Es scheint, dass in Ihrem Szenario einzelne '{}' in beiden Fällen ausreichen. Der enthaltene Typ ist "int", warum zu komplizieren? :-) – iammilind

Antwort

2

Aber std::vector<int> v = {{{}}}; tut nicht, was Sie denken; es initialisiert einen Vektor mit einem int Element, initialisiert auf Null. Dies liegt daran, int Liste initialisiert werden kann:

int i{}; // assert(i == 0) 

So wird std::vector<int> v = {{{}}}; analysiert als:

std::vector<int> v = {{{}}}; 
         ^-- int 
         ^-- initializer_list<int> 
        ^-- vector<int> 

Ebenso, wenn Sie

VInitList vil{{{}}}; 
       ^-- int 
       ^-- vector<int> 
      ^-- VInitList 

das enthaltene vector<int> hat 1 Element schreiben, initialisiert bis Null. (Die initializer_list<int> Bühne kann weggelassen werden, da der vector(initializer_list<int>) Konstruktor nicht explicit ist).

So VInitList vil({{}}); analysiert werden könnte als:

VInitList vil({{}}); 
       ^-- int 
       ^-- vector<int> 

oder als

VInitList vil({{}}); 
       ^-- vector<int> 
       ^-- VInitList 

Im ersten Fall ist die vector 1 Element aufweist; im zweiten Fall ist es leer. Es ist genauso gut, dass gcc den Code ablehnt.

Clang analysiert es nur als erster; Ich bin mir nicht sicher, was richtig ist.

+0

sehr interessant, ich wusste nicht int kann list-initialisiert werden. Warum ist das möglich? und wofür? – FrankS101

+1

@ FrankS101 Konsistenz, hauptsächlich - es bedeutet, dass Sie '{}' oder '= {}' überall dort verwenden können, wo ein Objekt auf seinen "leeren" Zustand initialisiert werden soll. Beachten Sie, dass Sie in C++ 98 '' '' an Stellen verwenden könnten, die nicht mit einer Funktionsdeklaration verwechselt werden, z. Mitgliedsinitialisierer: 'struct S {int i; S(): i() {}}; ' – ecatmur

Verwandte Themen