質問

可能な限りstd::stringではなくchar*を使用しようとしていますが、パフォーマンスが低下しすぎるのではないかと心配しています。これは文字列を返すのに良い方法ですか(簡潔さのためのエラーチェックはありません)?

std::string linux_settings_provider::get_home_folder() {
    return std::string(getenv("HOME"));
}

また、関連する質問:パラメーターとして文字列を受け入れるとき、const std::string&またはconst char*として受け取るべきですか?

ありがとう。

役に立ちましたか?

解決

文字列を返します。

より良い抽象化は価値があると思います。有意義なパフォーマンスの違いを測定できるようになるまで、それはあなたの想像力にのみ存在するミクロ最適化だと主張します。

C ++に文字列を抽象化するのに何年もかかりました。 Bjarne Stroustroupは保守的な<!> quot;使用した分だけ支払う<!> quot;で有名だとは思いません。口論は、言語への明らかなパフォーマンスキラーを許可したでしょう。より高い抽象化は良いことです。

他のヒント

誰もが言うように、文字列を返します。

文字列をパラメーターとして受け入れる場合、const std::string&またはconst char*として受け取るべきですか?

値で取るほど軽量であるか、nullポインタが<!> quot; noneを意味する有効な入力である必要があるまれな場合を除いて、参照によってconstパラメータを取ります上記の<!> quot;。このポリシーは文字列に固有のものではありません。

非定数の参照パラメーターは議論の余地があります。呼び出しコードから(適切なIDEがない場合)、値渡しまたは参照渡しのどちらであるかをすぐに見ることができず、違いが重要です。そのため、コードが不明瞭になる場合があります。 const paramsには適用されません。呼び出し元のコードを読んでいる人は、通常、それが自分の問題ではないと想定することができるため、署名を確認する必要があるのはたまにしかありません。

関数内の引数のコピーを取得する場合、一般的なポリシーは引数を値で取得することです。次に、使用できるコピーが既にあり、それを特定の場所(データメンバーなど)にコピーした場合は、(C ++ 11で)移動するか、(C ++ 03で)交換できますそこに着く。これにより、コンパイラは、呼び出し元が一時オブジェクトを渡すケースを最適化する最適な機会を提供します。

特にstringの場合、これは関数が値でstd::stringを取り、呼び出し側が引数式として文字列リテラルまたはnullで終わる文字列を指すchar*を指定する場合を扱います。 <=>を取得して関数にコピーした場合、2つの文字列が作成されます。

値によって文字列をコピーするコストは、使用しているSTL実装によって異なります。

    MSVCでの
  • std :: stringは短い文字列の最適化を使用するため、短い文字列(<!> lt; 16文字iirc)はメモリ割り当てを必要としません(std :: string内に保存されます)それ自体)、より長いものは文字列がコピーされるたびにヒープ割り当てが必要です。

  • GCCでの
  • std :: stringは、参照カウント実装を使用します。char*からstd :: stringを構築する場合、毎回ヒープ割り当てが行われますが、値を関数に渡す場合、参照カウント単純にインクリメントされ、メモリ割り当てを回避します。

一般に、1秒間に何千回も実行していない限り、上記のことを忘れて値ごとにstd :: stringsを返すことをお勧めします。

re:パラメータの受け渡し。char*-<!> gt; std :: stringからはコストがかかりますが、std :: string-<!> gt; char *からはコストがかかりません。一般に、これは、std :: stringへのconst参照を受け入れた方がよいことを意味します。ただし、const std :: string <!> amp;を受け入れるための最適な理由。引数として、呼び出し先はチェックとnullの比較のために余分なコードを持つ必要がないということです。

良いアイデアのようです。

これがリアルタイムソフトウェア(ゲームなど)の一部ではなく、通常のアプリケーションの一部である場合は、それで十分です。

覚えておいてください、<!> quot; 早期最適化はすべての悪の根源です <!> quot;

特にプログラミング言語が低レベルの最適化をサポートしている場合、パフォーマンスを心配するのは人間の性質です。 ただし、プログラマとして忘れてはならないのは、プログラムのパフォーマンスが最適化および称賛できる多くのことの1つにすぎないということです。プログラムの速度に加えて、私たち自身のパフォーマンスに美しさを見つけることができます。最大の視覚的出力とユーザーインターフェイスの対話性を実現しようとしながら、作業を最小限に抑えることができます。長い目で見ればビットとサイクルを心配するより多くの動機になると思いますか?そう、そう、string:sを返します。コードのサイズと労力を最小限に抑え、あなたの労力を抑えます。

あなたの場合、戻り値の最適化が行われるため、std :: stringはコピーされません。

モジュールの境界を越えるときは注意してください。

C ++型は必ずしも同じコンパイラの異なるバージョン間でもバイナリ互換ではないため、プリミティブ型を返すのが最善です。

文字列を使用する必要があることを他のポスターに同意します。

しかし、コンパイラがテンポラリーをどれだけ積極的に最適化するかによって、余分なオーバーヘッドが発生する可能性があります(charsの動的配列を使用する場合よりも)。 (注:C ++ 0aでは、右辺値参照の賢明な使用は、ここで効率を購入するためにコンパイラーの最適化を必要としないということです-プログラマーは、品質に依存せずにコードのパフォーマンスをさらに保証できますコンパイラ。)

あなたの状況では、余分なオーバーヘッドは手動メモリ管理を導入する価値がありますか?最も合理的なプログラマーは同意しません-しかし、アプリケーションがパフォーマンスの問題を抱えている場合、次のステップはアプリケーションをプロファイルすることです-したがって、複雑さを導入する場合、改善する必要があるという十分な証拠が得られた後にのみそれを行います全体的な効率。

誰かが、戻り値の最適化(RVO)はここでは無関係であると述べました-私は同意しません。

これに関する標準テキスト(C ++ 03)は(12.2)です:

[標準引用の開始]

  

クラス型のテンポラリはさまざまなコンテキストで作成されます。右辺値を参照にバインド(8.5.3)、右辺値を返す(6.6.3)、右辺値を作成する変換(4.1、5.2.9、5.2.11) 、5.4)、例外のスロー(15.1)、ハンドラーの入力(15.3)、およびいくつかの初期化(8.5)。 [注:例外オブジェクトの存続期間は15.1で説明されています。 ]一時オブジェクトの作成が回避された場合でも(12.8)、すべてのセマンティック   一時オブジェクトが作成されたかのように制限を尊重する必要があります。 [例:コピーコンストラクターが呼び出されない場合でも、アクセシビリティ(11節)などのすべてのセマンティック制限が満たされるものとします。 ]

 [Example:  
struct X {
  X(int);
  X(const X&);
  ˜X();
};

X f(X);

void g()
{
  X a(1);
  X b = f(X(2));
  a = f(a);
}
  

ここで、実装はX <!>#8217; s copy-constructorを使用してf()に渡す前にX(2)を構築する一時的なものを使用する場合があります。あるいは、引数を保持するために使用されるスペースにX(2)が構築される場合があります。また、X <!>#8217; s copyconstructor;を使用してbにコピーする前に、f(X(2))の結果を保持するために一時ファイルが使用される場合があります。あるいは、f()<!>#8217; sの結果はbで作成される場合があります。一方、式a = f(a)は、引数aまたはf(a)の結果の一時的な値を必要とし、   a。 ]

[標準引用の終了]

本質的に、上記のテキストは、初期化の状況ではRVOに依存できるが、割り当ての状況ではできない可能性があることを示しています。その理由は、オブジェクトを初期化するとき、オブジェクトを初期化するものがオブジェクト自体にエイリアスされることはないためです(コピーコンストラクターでセルフチェックを実行しないのはこのためです)。割り当て、それができます。

RVOを本質的に禁止するコードについては何もありませんが、実際に必要な場合は、コンパイラのドキュメントを読んで、本当に信頼できることを確認してください。

duffymoに同意します。最初に理解できる実用的なアプリケーションを作成し、次に必要に応じて攻撃の最適化を行う必要があります。この時点で、主要なボトルネックがどこにあるのかがわかり、より高速なアプリを作成するための時間をより効率的に管理できるようになります。

@duffymoに同意します。測定するまで最適化しないでください。これは、マイクロ最適化を行うときに2倍になります。そして常に:最適化したおよびを測定して、実際に物事をより良くしたかどうかを確認します。

文字列を返します。パフォーマンスの面ではそれほど大きな損失ではありませんが、その後の作業は確実に楽になります。

さらに、関数はいつでもインライン化できますが、ほとんどのオプティマイザーはそれを修正します。

参照された文字列を渡し、その文字列を操作する場合、何も返す必要はありません。 ;)

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top