2012-03-31 16 views
7

W tym fragmencie kodu, który konstruktor jest faktycznie wywoływany?Który konstruktor jest tutaj wywoływany?

Vector v = getVector(); 

wektor ma konstruktor kopiujący, domyślnego konstruktora i operatora przypisania:

class Vector { 
public: 
    ... 
    Vector(); 
    Vector(const Vector& other); 
    Vector& operator=(const Vector& other); 
}; 

getVector zwrotu przez wartość.

Vector getVector(); 

Kod wykorzystuje standard C++ 03.

Fragment kodu wygląda tak, jakby miał wywołać konstruktor domyślny, a następnie operator przypisania, ale podejrzewam, że ta deklaracja jest inną formą korzystania z konstruktora kopiowania. Który jest poprawny?

Odpowiedz

8

Gdy = pojawia się podczas inicjalizacji, wywołuje konstruktor kopiowania. Ogólna forma nie jest dokładnie taka sama, jak bezpośrednie wywołanie konstruktora kopiowania. W przypadku instrukcji T a = expr;, jeśli wyr jest typu T, wywoływany jest konstruktor kopiowania. Jeśli expr nie jest typu T, to najpierw, jeśli to możliwe, wykonywana jest niejawna konwersja, wówczas konstruktor kopiowania jest wywoływany z tym jako argument. Jeśli niejawna konwersja nie jest możliwa, kod jest źle sformułowany.

W zależności od tego, jak getVector() jest skonstruowany, kopia może zostać zoptymalizowana od hotelu, a obiekt, który powstał wewnątrz funkcji jest taki sam obiekt fizyczny, który zostanie zapisany w v.

+0

Jedna zasada nie mająca żadnej wartości jest taka, że ​​konstruktor kopii musi być dostępny (np. Publiczny), nawet jeśli sama konstrukcja kopii zostanie wyeliminowana. Możliwe, że konstruktor kopiowania będzie prywatny, kod nie skompiluje się, a upublicznienie go skompiluje, ale konstruktor kopiowania nie zostanie wywołany. – 6502

+0

"ten sam obiekt fizyczny, który zostanie zapisany w v" - raczej obiekt utworzony wewnątrz funkcji jest tym samym obiektem fizycznym co 'v'. Normalnie powiedziałbym, że 'v' jest nazwą obiektu, lub' v' jest tym obiektem, ale nie "obiekt jest przechowywany w' v ". Zwykle implementacja tej metody kopiowania polega na tym, że wywołujący 'getVector' przekazuje wskaźnik jako dodatkowy ukryty parametr, a' getVector' konstruuje jego wartość zwracaną pod tym adresem. W takim przypadku standard zezwala, aby kod wywołujący przekazał '& v' jako ukryty parametr. –

0

Konstruktor kopia faktycznie dostaje pomijana w ten przypadek (sprawdź this) i po prostu domyślny konstruktor kończy się nazywa coraz

EDIT:

konstruktor jest tylko czasami pomijana, a za odpowiedź Benjamina. Z jakiegoś powodu przeczytałem to, gdy dzwonisz bezpośrednio do konstruktora.

2

Zakładając, że nie zrobili coś patologicznego poza kodem pokazujesz, twoja deklaracja jest kopią inicjalizacja, a druga część tej reguły dotyczy:

13.3.1.3 Initialization by constructor [over.match.ctor] 

1 When objects of class type are direct-initialized (8.5), or copy-initialized from an 
    expression of the same or a derived class type (8.5), overload resolution selects the 
    constructor. For direct-initialization, the candidate functions are all the constructors 
    of the class of the object being initialized. For copy-initialization, the candidate 
    functions are all the converting constructors (12.3.1) of that class. The argument 
    list is the expression-list within the parentheses of the initializer. 

Dla prostego przypadku testowego , patrz post Eli Bendersky, oto: http://eli.thegreenplace.net/2003/07/23/variable-initialization-in-c/

1

Zawsze pamiętaj o zasadzie:
Kiedykolwiek, obiekt jest tworzony i dał jakąś wartość w tym samym pojedynczym sprawozdaniu to jest nigdy zadanie.

Aby dodać Ponadto

Przypadek 1:

Vector v1; 
Vector v(v1); 

Przypadek 2:

Vector v = getVector(); 

W powyższych dwóch formatach Przypadek 1 jest bezpośrednie inicjalizacji, gdy Przypadek 2 jest znany jako inicjowanie kopii.

Jak działa inicjowanie kopiowania?
Inicjalizacja kopiowania tworzy niejawną sekwencję konwersji: próbuje przekonwertować wartość zwracaną z getVector() na obiekt typu Vector. Następnie może skopiować utworzony obiekt do zainicjowanego obiektu, więc potrzebuje dostępnego konstruktora kopiowania.

Powiązane problemy