3

例として次の関数を取り上げます

string print()
{
   return (some string that has been formed);
};

そして、この print 関数がとてつもなく大きな文字列を形成し、それを別のクラスから呼び出した関数に戻す必要があるとしましょう。

ここで、この印刷関数が何千回も呼び出される可能性があるとします。これを行うための正しくて速い方法はありますか?

Visual Studioではこれを行うことができます

void print(string& lines)
{
   lines = (some string that has been formed);
};

ただし、g++ はこれをコンパイルしません。また、これは一時的なオブジェクトであり、いつでも消える可能性があるため、この方法で実行する必要はありません。だから私が理解していることから、私はこれを行うことができるということです

void print(const string& lines)
{
};

私が望んでいたのは、この文字列を変更せずに何かを取得し、非常に迅速に実行することだけでした。しかし、私はそれを変更したいです。だから、これは私にはできません。

これを行うには、オブジェクトへの新しいポインターを宣言するのが最速の方法になるという質問に私を導きますか? それとも遅いですか?それともそれだけの価値がないのですか?すなわち(これがうまくいくかどうかわからない?)

void print(string* lines)
{
   string formedString; // the string that has been formed
   lines = formedString&;
};

最後に、実行時にオブジェクトをロードし、次の方法でツリーに追加するとします。

void add(const ItemType& item)
{
   someNode->item = item;
};

itemは元々、 this を呼び出す関数のスコープ内に一時的に格納されたオブジェクトでした。add()そのため、それをノードに割り当てると、呼び出し関数のスタックが必要以上に長く滞在することになりますか? それともこれでいいでしょうか?また、後で編集できるようになりますitemか、それとも const としてスタックしていますか?

学習心の質問です:)

4

2 に答える 2

8

文字列を返すだけで完了です。

コンパイラは、戻り値の最適化 (または名前付きの戻り値の最適化) を使用して、文字列を返すときに余分なコピーを削除します。本当に新しいコンパイラには、 の移動コンストラクタと移動代入演算子std::stringもあり、同じことを達成することがさらに保証されます。

編集(申し訳ありませんが、最初は最後の質問を見逃していました):値を割り当てると、その関数が戻った後、その関数にローカルなものは何も保持されません。関数が戻ると、そのローカル変数すべて破棄されます。その関数からの値を、それが返された後も存続するものに代入する場合、それは問題ありません。それは宛先にコピー (または移動) されます。そのローカルへのポインターまたは参照を保持すると、関数が戻った後にぶら下がっているため、ポインターの参照または逆参照を使用しようとすると、UB が発生します。

状況によっては、後者の場合は を使用する場合があるshared_ptrため、関数と外部コードの両方がデータへのアクセスを共有し、データへの両方の参照が破棄された場合にのみデータが破棄されます。

于 2013-03-28T02:31:21.573 に答える
2

C++11、または基本的な C++11 機能を備えたコンパイラでは、答えは次のとおりです。

スピードが欲しいですか?移動セマンティクスをサポートするオブジェクトを使用して、値で渡します。

そして、あなたのstringタイプ (それが a でstd::stringあろうと何を持っていようと) は、高速移動のセマンティクスをサポートする必要があります。

関数からローカル変数を返す場合、C++11 では暗黙的に戻り値に移動されます。関数の本体が呼び出し元のサイトから表示され、関数からの戻り値である変数が 1 つある場合、NRVO が発生して、コピーや移動が発生しない可能性があります (むしろ、オブジェクトは最終的に最終的に構築されます)。呼び出しサイト)。

最終的に渡された引数のコピーを作成したい場合はいつでも、同様にパラメーターで値渡しを使用します。これにより、呼び出し元はいくつかのコンテキストで pass-by-move を実行でき、呼び出し元std::moveは非自動コンテキストで明示的に実行できるため、非常に優れたパフォーマンスが得られます。

コピーを作成しない場合はconst string&、一時的にバインドできる を渡します。

string& pass byまたはpass byのいずれかでデータを変更している場合stringは、戻り値の一部として新しい文字列を返します。速い動きの構築では、2 番目は最悪の場合でも 1 番目とほぼ同じ速さであり、場合によってはより速くなる可能性があります (NRVO の複数の連鎖は理論的には 2 番目のケースで可能です!)

于 2013-03-28T02:31:29.897 に答える