copy initialization은 아래와 같은 스타일이다
int x = 5;
int 타입의 경우 위처럼 간단하지만 class의 경우 좀 더 복잡하다
이번 섹션에서는 class의 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);
}
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은 피하는 것이 좋다
우리가 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를
생략하기도 한다