Brise

[C++ 기본 2] 11. 복사 생성자 본문

프로그램/C,C++

[C++ 기본 2] 11. 복사 생성자

naudhizb 2022. 3. 3. 00:09
반응형
// 11_복사생성자  92 page
#include <iostream>

class Point
{
    int x, y;
public:
    Point()             : x(0), y(0) {} // 1
    Point(int a, int b) : x(a), y(b) {} // 2

    // 복사 생성자 : 자신과 동일 타입 객체를 인자로 받는 생성자
    // 사용자가 만들지 않으면 컴파일러가 제공해 준다
    Point(const Point& pt)
        : x(pt.x), y(pt.y)
    {
        std::cout << "copy constructor" << std::endl;
    }
};

int main()
{
    Point p1;        // 1번 생성자
    Point p2(1, 1);    // 2번 생성자

    //Point p3(1);    // Point(int) 모양의 생성자 필요.
                    // 없으므로 error

    Point p4(p2);    // Point(Point) 모양의 생성자가 필요
                    // 없지만 ok.

    Point p5 = p2;  // 복사 생성자. 직접이 아닌 복사 초기화
}

복사 생성자는 자신과 동일 타입을 인자로 받아 초기화를 수행한다.

// 11_복사생성자2
// 11_복사생성자  92 page
#include <iostream>
// 복사 생성자가 사용되는 경우 3가지 - 96 page
// 1. 객체 생성시 자신과 동일타입 객체로 초기화 할때

// 2. 함수가 인자를 call by value 로 전달 받을때
//            => const 레퍼런스를 사용하자.!

// 3. 함수가 값 타입으로 객체를 반환 할때
//            => 임시객체가 생성되면서 복사 생성자 호출.

class Point
{
    int x, y;
public:
    Point()                : x(0), y(0) {} 
    Point(int a, int b)    : x(a), y(b) {} 
    Point(const Point& pt) : x(pt.x), y(pt.y){    std::cout << "copy constructor" << std::endl;    }
};
//void foo(Point pt) {} // Point pt = p1;
void foo(const Point& pt) {} // const Point& pt = p1;

int main()
{
    Point p1(1, 2); // 2번 생성자
    //Point p2(p1);   // 복사 생성자
    //Point p3 = p1;  // 복사 생성자

    foo(p1);
}

일반적으로 const 레퍼런스 타입을 받아 복사 생성자를 사용한다.

// 11_복사생성자2
// 11_복사생성자  92 page
#include <iostream>
// 복사 생성자가 사용되는 경우 3가지 - 96 page
// 1. 객체 생성시 자신과 동일타입 객체로 초기화 할때

// 2. 함수가 인자를 call by value 로 전달 받을때
//            => const 레퍼런스를 사용하자.!

class Point
{
    int x, y;
public:
    Point() : x(0), y(0)             { std::cout << "생성자1" << std::endl; }
    Point(int a, int b) : x(a), y(b) { std::cout << "생성자2" << std::endl; }
    Point(const Point& pt) : x(pt.x), y(pt.y) { std::cout << "copy constructor" << std::endl; }
    ~Point() { std::cout << "~Point()" << std::endl; }
};
Point foo()  // return by value
{
    Point pt(1,2);
    return pt; // 이순간 리턴용 임시객체가 생성됩니다.
                // 리턴용 임시객체를 pt를 복사해서 생성
}
int main()
{
    Point ret;
    std::cout << "----" << std::endl;
    ret = foo();
    std::cout << "----" << std::endl;
}
// 생성자1
// -----
// 생성자2
// 복사 생성자 - 리턴용 임시객체를 만들기 위해
// 소멸자 - pt 파괴
// 소멸자 - 리턴용 임시객체 파괴
//------
// 소멸자 - ret 파괴.

만약 함수가 클래스를 반환한다면, return by value이기 때문에 복사 생성자를 이용하여 복사된 클래스를 생성하고 리턴을 수행한다.

// 11_복사생성자2
#include <iostream>

class Point
{
public:
    int x, y;

    Point() : x(0), y(0) { std::cout << "생성자1" << std::endl; }
    Point(int a, int b) : x(a), y(b) { std::cout << "생성자2" << std::endl; }
    Point(const Point& pt) : x(pt.x), y(pt.y) { std::cout << "copy constructor" << std::endl; }
    ~Point() { std::cout << "~Point()" << std::endl; }
};

Point pt(1, 1); // 전역 객체
Point foo()     // 값 반환 : 임시객체가 반환된다.
{
    return pt; 
}
Point& goo()     // 참조 반환 : 임시객체를 만들지 말라는것
{                    // 99page 마지막 소스
    return pt;
}

int main()
{
    foo().x = 10; // error. temporary 는 왼쪽에 올수없다
    goo().x = 10; // ok

    cout << "A" << "B" << "C";
}

// 정리
n = x;
x = 10;
// 1. primitive
int  foo() { return x; } // x의 값. 
int& goo() { return x; } // x 자체 (메모리)

// 2. user type
Point  foo() { return pt; } // 임시객체
Point& goo() { return pt; } // pt의 자체(메모리)

만약 함수가 클래스 레퍼런스를 반환하는 경우에는 복사 생성자를 호출하지 않고 클래스 자체를 반환하게 된다.

반응형

'프로그램 > C,C++' 카테고리의 다른 글

[C++ 기본 3] 1. 객체복사  (0) 2022.04.04
[C++ 기본 2] 내용 정리  (0) 2022.04.04
[C++ 기본 2] 12. 객체 복사(shallow copy)  (0) 2022.03.03
[C++ 기본 2] 10. explicit  (0) 2022.03.02
[C++ 기본 2] 9. 초기화리스트  (0) 2022.03.02
[C++ 기본 2] 8. 생성자  (0) 2022.03.02
[C++ 기본 2] 7. 접근지정자  (0) 2022.03.02
Comments