C++:コンストラクション関数、コピーコンストラクション関数、移動コンストラクション関数、コピー付与演算子、移動付与演算子適用シーン


コンストラクション関数、コピーコンストラクション関数、移動コンストラクション関数、コピー付与演算子、移動付与演算子適用シーン
#include 
using namespace std;

class ConstructTest{
public:
    ConstructTest(){
        cout<>>>>>>>
"; }

C++とJAVAが違うのは、C++は値タイプと参照タイプを区別しており、JAVAのようにすべて参照タイプではありません.オブジェクト作成JAVA用  オブジェクト名=new…  C++はオブジェクト名でいいです.通常のオブジェクトに対して値で伝達される方法でパラメータに伝達される暗黙的に値を付与するプロセスがあります.このとき呼び出されるコピーコンストラクション関数です.以下のコンストラクション関数はシーンを使用します.
コンストラクタ : オブジェクトの作成時に、オブジェクトの初期化時に呼び出されます.
コピー(コピー)コンストラクタ:同じクラスオブジェクトを使用して新しいオブジェクトを初期化する.時に呼び出す.
コピー代入演算子:2つの古いオブジェクト間の代入.
「移動」とは,aのメモリリソースを自用に移動することである.
≪コンストラクション関数の移動|Moveコンストラクション関数|emdw≫:オブジェクトの作成時に一時オブジェクトで初期化されたときに呼び出されます.戻り値が戻り値のコピーに渡されると呼び出されます.
割り当て演算子の移動: 一時オブジェクトで古いオブジェクトに値を割り当てるときに呼び出されます.
 
私はCLIONを使って、CMakeList.txtで以下のコードを加えて、コンパイラの最適化を取り消します
add_compile_options(-fno-elide-constructors)

コンパイラ最適化なしで結果を出力:
Constructor with param
copy Constructor
default Constructor
copy assign
------------------------
default Constructor
copy Constructor
Constructor with param
moving copy Constructor
Destructor:base 0
moving copy assign
Destructor:base 0
Destructor:base 0x3e1da8
------------------------
moving copy Constructor
------------------------
default Constructor
default Constructor
moving copy assign
Destructor:base 0
copy Constructor
Constructor with param
moving copy Constructor
Destructor:base 0
moving copy Constructor
Destructor:base 0
Destructor:base 0x3e1da8
default Constructor
moving copy Constructor
Destructor:base 0
<<<<<>>>>>>>
Destructor:base 0
Destructor:base 0x3e1918
Destructor:base 0
Destructor:base 0x3e1dd8
Destructor:base 0
Destructor:base 0x3e1d90
Destructor:base 0x3e1d78
Destructor:base 0x3e1d60

Process finished with exit code 0

main関数の1行目から4行目には,構造関数,コピー構造,およびコピー付与が示されている.
5行目から:
 cout<

まずデフォルトのコンストラクション関数でオブジェクトc 5を作成し、
c 5=square(c 4)では,まず実パラメータc 4をsquareの形パラメータparamに付与し,このときコピー構造関数を用いる.
square関数体でローカルオブジェクトretが作成され、コンストラクション関数が呼び出されます.
次に戻り値retのコピーを作成し、移動構造関数を呼び出し、関数体が終了し、パラメータparamを解析します.
その後、元のretのコピーをc 5に付与し、プロセスは既存のオブジェクトc 5に付与するので、移動付与を呼び出す.
次にretとretのコピーを解析する.
std::move()を用いる、c 5の内容をある一時参照に手動で移動し、一時参照をc 6に初期化し、移動構造関数を呼び出す.
    cout<>>>>>>>
";

デフォルトのコンストラクション関数でc 7オブジェクトを作成します.
デフォルトのコンストラクション関数で一時オブジェクトを作成し、一時オブジェクトをc 7に「移動」します.移動後に一時オブジェクトをプロファイルする
c 8で = square(c 7)では,まず実パラメータc 7をsquareの形パラメータparamに付与し,このときコピー構造関数を用いる.
square関数体でローカルオブジェクトretが作成され、コンストラクション関数が呼び出されます.
次に戻り値retのコピーを作成し、移動構造関数を呼び出し、関数体が終了し、パラメータparamを解析します.
その後、元retのコピーをc 8に割り当て、まだ作成されていないオブジェクトのオブジェクトc 8を初期化するので、移動構造を呼び出す.
次にretとretのコピーを解析する.
一時オブジェクトを作成し、c 9に初期化し、最後に一時オブジェクトを解析する.
プログラムが終了し、すべての変数を解析します.
プログラミング構想
    クラスメンバー変数にポインタがある場合、リソースをどのように適用するかという難題に直面します.デフォルトのコピー構造、コピーに値を割り当てる必要があります.移動構造、移動に値を割り当てるのは、単純な浅いコピーにすぎません.つまり、値レプリケーションポインタがメモリのアドレスを指します.浅いコピー後、2つのオブジェクトのメンバーポインタが同じメモリ領域を指し、構造関数でメンバーポインタdeleteを使用すると、最後に同じメモリ領域に2回適用されます.C++では、本プログラムに属さないメモリにアクセスすると「セグメントエラー」、すなわちポインタが境界を越える. 
    プログラミング時にboost::shared_を利用できますptrは、動的に割り当てられたメモリを管理します.この場合、リソースの割り当ての問題を無視できます.スマートポインタは、ダイナミックメモリの参照カウントをゼロにすると、メモリ領域を自動的にクリーンアップすることができるからです.
   ダイナミックメモリを通常のポインタで管理する場合は、リソースの適用、浅いコピー、深いコピーの問題を考慮します.深いコピーを使いたい場合は、構造関数、コピー構造関数、コピー付与演算子、移動構造、移動付与演算子を書きます.
  コンストラクション関数ですべてのメンバー変数を初期化するには、ポインタが含まれます.コピー構造とコピー付与でポインタにメモリ領域を再割り当てし、対応するメモリ値を付与する.移動構造と移動賦値では、戻るコンテンツをコピーした後、一時的なオブジェクトポインタの内容を空にし直す、メモリをコピーせずにメモリを2回も置かない目的、いわゆる「移動」を達成する.