2

関数内でreturnステートメントを使用してユーザー定義型(特にクラス)を返すとどうなりますか。「DMatrix」というc++クラスがあるとします。

DMatrix someFunc()
{  
  DMatrix mymat;
  /* Some operations on this matrix */  
  return mymat;  
};

main()内のどこかで、やりたいです:

DMatrix d;
d = someFunc();

スタック操作に関して正確に何を呼び出しますか?
クラスDMatrixを返すには、コピーコンストラクター(このクラスのインスタンスを参照経由で渡すことができるようにするため)と=演算子を定義するだけで十分だと思います。私は正しいですか?

背後にある動機:この質問の背後にある動機は2つあります。1)マトリックスタイプを定義したライブラリを使用します。たとえば、DMatrixを使用します。DMatrixタイプを返す関数を書くことはできますか?
2)2番目の理由は、もちろん、カスタムデータ型の戻りとintやdoubleなどの基本データ型の戻りのスタックレベルでの違いをより深く理解することです。したがって、C++でより優れたクラスをコーディングします。これは別の質問にする必要があるかもしれません。

4

2 に答える 2

1

コピーコンストラクターを実装する必要がありますが、これは実際には、バイナリの「デバッグ」バージョンと「リリース」バージョンの間に意味上の違いが見られる興味深いシナリオの1つであることに注意してください。ほとんどのコンパイラは、コピーコンストラクタへの呼び出しを最適化し、このインスタンスで戻り値の最適化を実行します。コンパイラーは、この状況での仕様により、コピーコンストラクターを使用してこれを行うことが特に許可されています。

コピーコンストラクターで何かを印刷してみてください。リリースバージョンを実行すると印刷されませんが、デバッグバージョンでは印刷されます。

さらに、C ++ 11を使用している場合、mymatを返す時点で、mymatは右辺値(一時オブジェクト)と呼ばれるものになります。C ++ 11では、移動コンストラクターと、コピーを実行せずにオブジェクトを外部スコープに明示的に移動するコピーコンストラクターを宣言することができます。

于 2012-11-08T14:04:58.490 に答える
0

コンパイラが小さなクラスを返すために異なる手法を使用する可能性があるため、DMatrix8バイト()以上が必要であると想定します。sizeof(DMatrix) > 8

コードで

int main() {
    //...
    DMatrix d;
    d = someFunc();
    //...
}

ほとんどのコンパイラは、そのコードを次のようなものに「書き換え」ます。

DMatrix d;
DMatrix __retval;
someFunc(__retval);
d = __retval;

同時に、次のsomeFuncようなものに「書き直され」ます

void someFunc(DMatrix& __retval) {
    DMatrix mymat;
    /* Some operations on this matrix */
    // move/copy mymat into __retval
}

したがって、大規模なクラスの場合、ほとんどのコンパイラは、その型の戻り値を関数のパラメータに変換し、呼び出し元の関数の戻り値にストレージを割り当てます。

上記の説明では、存在する最適化の可能性を利用していないため、「最悪の場合」の動作を示しています。


関数から型を返すことができるようにするには、型に少なくともmove-constructor(C ++ 11のみ)またはcopy-constructorが必要です。タイプが何らかのリソース(たとえば、新規/削除を伴うメモリ)を明示的に管理しない限り、コンパイラが適切なリソースを生成するため、通常、それらを自分で書き込む必要はありません。

于 2012-11-08T15:16:16.460 に答える