13.12 The copy constructor
https://www.learncpp.com/cpp-tutorial/the-copy-constructor/
初期化については、以下のレッスンで説明します.
まずc++がサポートする初期化についてまとめます
direct init、uniform init、copy initなどがあります
サンプルコードを使用して表示
クラスで定義されているFraction(int,int)コンストラクタを呼び出します
ではfCopyの場合は何でしょうか.
このケースに注目しなければなりません
fCopyの場合、同じ分割タイプのFiveThirdsオブジェクトをパラメータで渡します.
これをcopy構造関数と呼ぶ.これは既存のobjectを用いてコンストラクション関数を起動する場合である.一般的には、copyコンストラクション関数を作成しない限り、C++はデフォルトバージョンです.
私たちのニーズに合えばdefault copy constructorを使うのも大きな問題ではありません.
計画どおりに実施すればよい
ここで注意したいのは、copy constructorでは同じオブジェクトではありませんが、スコアのprivate member変数にアクセスできます.つまり、同じタイプの場合、同じオブジェクトでなくても互いのプライベートメンバー変数にアクセスできます.
copy constructorをprivateに設定するとコンパイルエラーが発生します
しかし、現実にはこのような理由はない.
c++で省略し、
Recapping the types of initialization
初期化については、以下のレッスンで説明します.
まずc++がサポートする初期化についてまとめます
direct init、uniform init、copy initなどがあります
サンプルコードを使用して表示
#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;
}
私たちは次のようにdirect initを行うことができます.int x(5); // Direct initialize an integer
Fraction fiveThirds(5, 3); // Direct initialize a Fraction, calls Fraction(int, int) constructor
c++11で統合initが可能int x { 5 }; // Uniform initialization of an integer
Fraction fiveThirds {5, 3}; // Uniform initialization of a Fraction, calls Fraction(int, int) constructor
最後にinitをコピーすることもできますint x = 6; // Copy initialize an integer
Fraction six = Fraction(6); // Copy initialize a Fraction, will call Fraction(6, 1)
Fraction seven = 7; // Copy initialize a Fraction. The compiler will try to find a way to convert 7 to a Fraction, which will invoke the Fraction(7, 1) constructor.
The copy constructor
#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 fiveThirds { 5, 3 }; // Direct initialize a Fraction, calls Fraction(int, int) constructor
Fraction fCopy { fiveThirds }; // Direct initialize -- with what constructor?
std::cout << fCopy << '\n';
}
上のコードからfivethirdは普通のdirect initであることがわかりますクラスで定義されているFraction(int,int)コンストラクタを呼び出します
ではfCopyの場合は何でしょうか.
このケースに注目しなければなりません
fCopyの場合、同じ分割タイプのFiveThirdsオブジェクトをパラメータで渡します.
これをcopy構造関数と呼ぶ.これは既存のobjectを用いてコンストラクション関数を起動する場合である.一般的には、copyコンストラクション関数を作成しない限り、C++はデフォルトバージョンです.
私たちのニーズに合えばdefault copy constructorを使うのも大きな問題ではありません.
#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& fraction)
: m_numerator{fraction.m_numerator}, m_denominator{fraction.m_denominator}
// Note: We can access the members of parameter fraction directly, because we're inside the Fraction class
{
// no need to check for a denominator of 0 here since fraction 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);
};
std::ostream& operator<<(std::ostream& out, const Fraction& f1)
{
out << f1.m_numerator << '/' << f1.m_denominator;
return out;
}
int main()
{
Fraction fiveThirds { 5, 3 }; // Direct initialize a Fraction, calls Fraction(int, int) constructor
Fraction fCopy { fiveThirds }; // Direct initialize -- with Fraction copy constructor
std::cout << fCopy << '\n';
}
上のコードはcopy構造関数の例です計画どおりに実施すればよい
ここで注意したいのは、copy constructorでは同じオブジェクトではありませんが、スコアのprivate member変数にアクセスできます.つまり、同じタイプの場合、同じオブジェクトでなくても互いのプライベートメンバー変数にアクセスできます.
Preventing copies
copy constructorをprivateに設定するとコンパイルエラーが発生します
しかし、現実にはこのような理由はない.
The copy constructor may be elided
#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 &fraction)
: m_numerator{fraction.m_numerator}, m_denominator{fraction.m_denominator}
{
// no need to check for a denominator of 0 here since fraction 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);
};
std::ostream& operator<<(std::ostream& out, const Fraction& f1)
{
out << f1.m_numerator << '/' << f1.m_denominator;
return out;
}
int main()
{
Fraction fiveThirds { Fraction { 5, 3 } };
std::cout << fiveThirds;
return 0;
}
main関数がfiveThirdsをanonymous Fractionオブジェクトに初期化していることがわかります.もしそうならcopyコンストラクション関数を実行する予定ですが、実際にはc++で省略し、
Fraction fiveThirds{ 5, 3 };
elisionと呼ぶReference
この問題について(13.12 The copy constructor), 我々は、より多くの情報をここで見つけました https://velog.io/@ikmy0ung/13.12-The-copy-constructorテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol