[解決済み] コピー保証のエリシオンはどのように機能しますか?
質問
2016年のOulu ISO C++標準化会議において、以下のような提案がなされました。 簡略化された値カテゴリによるコピーエリジョンの保証 は、標準化委員会によって C++17 に投票されました。
コピー除去の保証は具体的にどのように機能するのでしょうか。コピー除去がすでに許可されていたいくつかのケースをカバーするのでしょうか、それともコピー除去を保証するためにコードの変更が必要なのでしょうか。
どのように解決するのですか?
コピー除去は多くの状況下で許可されていました。しかし、たとえそれが許可されていたとしても、コードはコピーがエリジョンされていないかのように動作できなければなりません。つまり、アクセス可能なコピーおよび/または移動コンストラクタがなければなりませんでした。
保証されたコピー消去は、コピー/移動が消去される可能性のある特定の状況が実際にはコピー/移動を引き起こさないように、多くの C++ 概念を再定義します。 まったく . コンパイラーはコピーを消去しているのではなく、標準ではそのようなコピーは決して起こり得ないと言っているのです。
この関数を考えてみましょう。
T Func() {return T();}
非保証のコピー消去ルールの下では、これは一時的なものを作成し、その一時的なものから関数の戻り値に移動することになります。その移動操作
は
はエリジオンになりますが
T
は、たとえそれが使われなくても、アクセス可能な移動コンストラクタを持たなければなりません。
同様に
T t = Func();
のコピー初期化です。
t
. これは、コピー初期化
t
の戻り値で
Func
. しかし
T
は、たとえそれが呼び出されないとしても、移動コンストラクタを持たなければなりません。
コピーエリジョンを保証する は prvalue 式の意味を再定義します。 . C++17 以前では、prvalue は一時的なオブジェクトです。C++17 では、prvalue 式は単に 実体化 一時的なものですが、まだ一時的なものではありません。
prvalueを使用してprvalueの型のオブジェクトを初期化した場合、テンポラリーはマテリアライズされません。あなたが
return T();
を実行すると、これはprvalueを介して関数の戻り値を初期化します。その関数が返すので
T
を返すので、一時的なものは作成されず、prvalueの初期化は単に直接戻り値を初期化します。
理解すべきことは、戻り値がprvalueであるため、それは
オブジェクトではなく
であるということです。これは単にオブジェクトのイニシャライザであり、ちょうど
T()
と同じです。
をしたとき
T t = Func();
を実行すると、戻り値の prvalue が直接オブジェクトを初期化します。
t
というように、一時的な作成とコピー・移動の段階はありません。したがって
Func()
と等価な値を返します。
T()
,
t
が直接初期化されるのは
T()
を行った場合と全く同じように
T t = T()
.
もしprvalueが他の方法で使われた場合、prvalueは一時的なオブジェクトを実体化し、その式で使われます(または式がない場合は捨てられます)。ですから、もしあなたが
const T &rt = Func();
とすれば、prvalue は一時的なオブジェクトを実体化します(using
T()
をイニシャライザーとして使い)、その参照は
rt
に格納され、通常の一時的な寿命延長のものと一緒に格納されます。
保証されたエリシオンでできることのひとつは、動かないオブジェクトを返すことです。例えば
lock_guard
はコピーも移動もできないので、それを値で返す関数は作れませんでした。しかし、保証されたコピー消去を使用すると、それが可能になります。
保証されたエリジョンは、直接の初期化でも機能します。
new T(FactoryFunction());
もし
FactoryFunction
が返す
T
を値として指定した場合、この式は戻り値を割り当てたメモリにコピーしない。その代わりにメモリを確保し
割り当てられたメモリ
を直接関数呼び出しの戻り値メモリとして使用します。
つまり、値で返すファクトリー関数は、ヒープに割り当てられたメモリを意識することなく直接初期化することができるのです。そのため、これらの関数が
内部的に
が保証されたコピー消去のルールに従う限りは、もちろん、です。の型のprvalueを返さなければなりません。
T
.
もちろん、これも有効です。
new auto(FactoryFunction());
型名を書くのが嫌な人のために。
上記の保証はprvalueに対してのみ機能することを認識することが重要です。つまり、prvalueを返した場合は何も保証されません。 という名前の という名前の変数を返す場合は保証されません。
T Func()
{
T t = ...;
...
return t;
}
この例では
t
はまだアクセス可能なコピー/移動コンストラクタを持たなければなりません。そうです、コンパイラはコピー/移動を最適化しないように選択することができます。しかし、コンパイラはアクセス可能なコピー/移動のコンストラクタの存在を確認する必要があります。
したがって、名前付き戻り値の最適化 (NRVO) については何も変わりません。
関連
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み] error: 'ostream' does not name a type.
-
[解決済み】エラー:不完全な型へのメンバーアクセス:前方宣言の
-
[解決済み] explicit キーワードの意味は?
-
[解決済み] 文字列の単語を反復処理するにはどうすればよいですか?
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] コピーアンドスワップ慣用句とは?
-
[解決済み] C++11では、標準化されたメモリモデルが導入されました。その意味するところは?そして、C++プログラミングにどのような影響を与えるのでしょうか?
-
[解決済み] コピーエリジョンと戻り値の最適化とは何ですか?
-
[解決済み] インライン変数の仕組みは?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】C++エラー。アーキテクチャ x86_64 に対して未定義のシンボル
-
[解決済み】Visual Studio 2015で「非標準の構文; '&'を使用してメンバーへのポインターを作成します」エラー
-
[解決済み】識別子 "string "は未定義?
-
[解決済み] クラスにデフォルトコンストラクタが存在しない。
-
[解決済み】cc1plus:エラー:g++で認識されないコマンドラインオプション"-std=c++11"
-
[解決済み】エラー:strcpyがこのスコープで宣言されていない
-
[解決済み】指定範囲内の乱数で配列を埋める(C++)
-
[解決済み】標準ライブラリにstd::endlに相当するタブはあるか?
-
[解決済み】VC++の致命的なエラーLNK1168:書き込みのためにfilename.exeを開くことができません。
-
[解決済み] スタックアロケーションにより初期化されていない値が作成された