13.13 Copy initialization


https://www.learncpp.com/cpp-tutorial/copy-initialization/
copy初期化は次のスタイルです.
int x = 5;
intタイプの場合は上記と同様に簡単ですが、クラスの場合はもっと複雑です.
このセクションではclassのcopy初期化について説明します

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初期化評価は以下の通りである.
Fraction six(Fraction(6));
前述したように、前回習ったanonymousobjectなので.
elisionが発生するため、copyコンストラクション関数なしでコンストラクション関数を実行
しかしelidingはc++17までは保障されていないのでcopy初期化は避けたほうがよい.

Other places copy initialization is used


パラメータを渡したり返したりするときにcopyを使用して初期化します
#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コンストラクション関数はmakenegative関数でパラメータを渡すときに発生します.
次に、関数内で返される過程で発生します.
ただし、パラメータとreturn valueが特定の条件を満たす場合、コンパイラは
省略する