2013-05-24 10 views
5

Jestem nowy w programowaniu C++, kiedy robię niektóre programy w C++ mam wątpliwości, dlatego konstruktor kopiowania jest wywoływany, gdy przechodzę obiekt jako argument przez wartość funkcji. Proszę zobaczyć mój poniższy kod w tym, że przekazuję obiekt klasy jako argument przez wartość do funkcji display(), ale wywołanie konstruktora kopiowania, a następnie sterowanie uderza w funkcję display(), ale rozumiem, dlaczego tak jest, proszę o pomoc.dlaczego kopiować konstruktor jest wywołanie, gdy przekazujemy obiekt jako argument przez wartość do metody

#include "stdafx.h" 
#include <iostream> 
using namespace std; 

class ClassA 
{ 
    private: 
     int a, b; 
    public: 
     ClassA() 
     { 
      a = 10, b = 20; 
     } 
     ClassA(ClassA &obj) 
     { 
      cout << "copy constructor called" << endl; 
      a = obj.a; 
      b = obj.b; 
     } 
}; 
void display(ClassA obj) 
{ 
    cout << "Hello World" << endl; 
} 
int main() 
{ 
    ClassA obj; 
    display(obj); 
    return 0; 
} 

Odpowiedz

6

Aby opracować dwie odpowiedzi podane już trochę:

Podczas definiowania zmiennych być „tak samo jak” innej zmiennej, masz w zasadzie dwie możliwości:

ClassA aCopy = someOtherA; //copy 
ClassA& aRef = someOtherA; //reference 

Zamiast nie- referencje const lvalue istnieją oczywiście odwołania do stałych i referencje rvalue. Najważniejsze, co chcę tutaj zaznaczyć, to że aCopy jest niezależny od someOtherA, podczas gdy aRef jest praktycznie tą samą zmienną co someOtherA, to po prostu inne imię (alias) dla niego.

Parametry funkcji są zasadniczo takie same. Gdy parametr jest referencją, zostaje powiązany z argumentem, gdy funkcja jest wywoływana, i jest to po prostu alias dla tego argumentu. To znaczy, co zrobić z parametrem, robisz z argumentem:

void f(int& iRef) { 
    ++iRef; 
} 

int main() { 
    int i = 5; 
    f(i); //i becomes 6, because iRef IS i 
} 

Gdy parametr jest wartością, to tylko kopia argumentu, więc bez względu na to, co zrobić z parametrem, argument pozostaje bez zmian.

void f(int iCopy) { 
    ++iCopy; 
} 

int main() { 
    int i = 5; 
    f(i); //i remains 5, because iCopy IS NOT i 
} 

Po przejściu przez wartość parametr jest nowym obiektem. Musi być, ponieważ nie jest to ten sam argument, co niezależny. Tworzenie nowego obiektu, który jest kopią argumentu, oznacza wywołanie konstruktora kopiowania lub konstruktora ruchu, w zależności od tego, który argument ma wartość lwartości lub rwartości. W twoim przypadku sprawdzenie, że funkcja przechodzi przez wartość, jest niepotrzebne, ponieważ odczytujesz tylko ten argument.

Jest wytyczne od GotW #4:

Wolę przechodzącą Parametr tylko do odczytu przez const & jeśli tylko będzie czytać z niego (nie zrobić jego kopię).

4

Bo przechodząc przez wartość do funkcji oznacza, że ​​funkcja ma swoją własną kopię obiektu. W tym celu wywoływany jest konstruktor kopii.

void display(ClassA obj) 
{ 
    // display has its own ClassA object, a copy of the input 
    cout << "Hello World" << endl; 
} 

Należy pamiętać, że w niektórych przypadkach kopie mogą zostać usunięte, na przykład, jeśli do funkcji zostanie przekazana wartość tymczasowa.

2

Jak juanchopanza powiedział :, podajesz wartość, co powoduje wykonanie kopii. Jeśli chcesz tego uniknąć można przekazać przez odniesienie:

void display(const ClassA &obj) 

Na marginesie: Należy zadeklarować swoją kopię konstruktor podjąć argument jako const odniesienia:

ClassA(const ClassA &obj) 

W przeciwnym razie nie będzie potrafi używać ctor na nazwanych obiektach oznaczonych jako const lub z temporaries. Zapobiega to również przypadkowej zmianie przekazywanego obiektu.

Powiązane problemy