2

Javaのバックグラウンドから来て、私はC++のポインター/参照を理解しようとしています。関数からベクトルを返そうとしています。書き込み:

vector<char*> f(){
    vector<char*> vec;
    return vec;
}

ベクトルのコピーを返しますか?より良い方法は、次のようにベクトルへのポインタを返すことです。

vector<char*>* f(){
    vector<char*>* vec = new vector<char*>;
    return vec;
}

私は正しいですか、それともこれは完全に間違っていますか?

4

3 に答える 3

1

C++03 では、値による戻りが RVO (戻り値の最適化) につながる可能性が高く、不要なコピーが省略されます。C++11 では、移動セマンティクスがコピーを処理します。

では、そもそもなぜ値で返すのでしょうか? 動的なライフタイムを持つ不要なオブジェクトを防ぐためです。サンプルコードは、関数のユーザーが使用したい割り当てポリシーも考慮していません。

一般に、コンテナーを返すことは、C++11 でも依然として悪い考えです。コンテナー間を移動することはできず、コピーすることしかできないため、ユーザーをその特定のコンテナーに制限します。標準ライブラリは、この問題を で解決しOutputIteratorSます。あなたのアルゴリズムはおそらく次のように書かれます:

template<typename OutputIterator>
OutputIterator f(OutputIterator o);

このようにして、コンテナから抽象化し、元の問題を回避します。

于 2013-02-15T01:17:09.937 に答える
0

あなたは間違っています。これを C++ で行いたくないのです。そこにあるほとんどすべてのC ++コンパイラには、名前付き戻り値の最適化と呼ばれるものがありvecます。これは、スタック上の戻り値にスペースを割り当てることにより、(効果的に)コピーではなく、移動され、基本的に「その場で」構築されます。これにより、オーバーヘッドがなくなります。

これに関するウィキペディアの記事は、合理的な概要を示しています。

于 2013-02-15T01:04:15.360 に答える
0

私は正しいですか、それともこれは完全に間違っていますか?

これは、少なくとも移動セマンティクスが存在する C++11 では完全に間違っており、返す値のエイリアスを作成する必要がない限り(これはあなたの場合ではないようで、あったとしても、生のポインターではなく、スマート ポインターを使用する必要がある可能性があります)。

ベクトルを値で返すことは今では問題ありません。ほとんどの場合、C++98 であっても、コンパイラはとにかくコピー コンストラクター (および C++11 のムーブ コンストラクター) への呼び出しを省略します。これは(名前付き) 戻り値の最適化と呼ばれます。

C++11 では、標準ライブラリのすべてのコンテナーが移動コンストラクターをサポートしているため、コピーまたは移動が省略されていない場合でも、コンテナーを値で返すことは高価ではありません。

于 2013-02-15T01:04:24.940 に答える