13.13 Copy initialization

주홍영·2022년 3월 18일
0

Learncpp.com

목록 보기
156/199

https://www.learncpp.com/cpp-tutorial/copy-initialization/

copy initialization은 아래와 같은 스타일이다

int x = 5;

int 타입의 경우 위처럼 간단하지만 class의 경우 좀 더 복잡하다
이번 섹션에서는 class의 copy initialization에 대해서 다룬다

Copy initialization for classes

#include <cassert>
#include <iostream>

class Fraction
{
private:
    int m_numerator;
    int m_denominator;

public:
    // Default constructor
    Fraction(int numerator=0, int denominator=1)
        : m_numerator(numerator), m_denominator(denominator)
    {
        assert(denominator != 0);
    }

    friend std::ostream& operator<<(std::ostream& out, const Fraction& f1);
};

std::ostream& operator<<(std::ostream& out, const Fraction& f1)
{
	out << f1.m_numerator << "/" << f1.m_denominator;
	return out;
}

int main()
{
    Fraction six = Fraction(6);
    std::cout << six;
    return 0;
}

위의 코드를 실행시키면 의도한대로 실행된다

이런 형태의 copy initialization은 다음과 같이 evaluate된다

Fraction six(Fraction(6));

위처럼 된 경우 저번에 배운 레슨에 의해 anonymous object 이기 때문에
elision이 발생해서 copy constructor 없이 constructor가 실행된다
다만 eliding은 c++17 이전에서는 보장되지 않으므로 copy initialization은 피하는 것이 좋다

Other places copy initialization is used

우리가 argument를 pass하거나 return으로 돌려줄 때도 copy initialization이 사용된다

#include <cassert>
#include <iostream>

class Fraction
{
private:
	int m_numerator;
	int m_denominator;

public:
    // Default constructor
    Fraction(int numerator=0, int denominator=1)
        : m_numerator(numerator), m_denominator(denominator)
    {
        assert(denominator != 0);
    }

        // Copy constructor
	Fraction(const Fraction& copy) :
		m_numerator(copy.m_numerator), m_denominator(copy.m_denominator)
	{
		// no need to check for a denominator of 0 here since copy must already be a valid Fraction
		std::cout << "Copy constructor called\n"; // just to prove it works
	}

	friend std::ostream& operator<<(std::ostream& out, const Fraction& f1);
        int getNumerator() { return m_numerator; }
        void setNumerator(int numerator) { m_numerator = numerator; }
};

std::ostream& operator<<(std::ostream& out, const Fraction& f1)
{
	out << f1.m_numerator << "/" << f1.m_denominator;
	return out;
}

Fraction makeNegative(Fraction f) // ideally we should do this by const reference
{
    f.setNumerator(-f.getNumerator());
    return f;
}

int main()
{
    Fraction fiveThirds(5, 3);
    std::cout << makeNegative(fiveThirds);

    return 0;
}

위의 프로그램을 실행시키면 다음과 같은 결과가 출력된다

Copy constructor called
Copy constructor called
-5/3

첫번째 copy constructor는 makeNegative함수에서 argument를 전달하면서 발생하고
다음은 함수 내에서 return하는 과정에서 발생한다

하지만 argument와 return value가 특정 기준을 만족하면 컴파일러는 copy constructor를
생략하기도 한다

profile
청룡동거주민

0개의 댓글