c++
  • string
  • lambda
  • rvalue
  • 2016-11-18 5 views 0 likes 
    0

    カスタム文字列を渡す最も効果的な方法は何ですか。 例えば、私はこのコードセグメントを有する:文字列により-VAL戻され、その後もAで使用されているので、機能はそれほど有効ではないことは明らかである効率的なカスタム文字列作成者

    string addSpace(int n) { 
        string result(""); 
        for (int i = 0; i < n; i++) { 
         result += ' '; 
        } 
        return result; 
    } 
    

    outputFile << addSpace(data.len()); 
    

    をRValueにも適した場所。 Nが固定された場合は、Nは5 =と言う、私はちょうど

    outputFile << " "

    が、明らかにそれはない場合に使用することができます。

    だから、最良の解決策は何でしょうか(このN個の空白の特定の例に関係なく、パラメータに依存する文字列の作成については何も言えません)。 私はラムダ関数について考えましたが、私はあまりよく分かりません。

    +2

    おそらく "効率的"を意味するでしょう... –

    +0

    'data.len'には妥当な上限があり、関数を非常に頻繁に呼び出すと、生成された各文字列をキャッシュすることができます。文字列の関数静的配列(または連想配列)をチェックし、チェックする長さのインデックスとそれがあれば、キャッシュされた値を返します。または、もっと鈍い、最大のlenが小さい場合、すべての文字列を事前に生成します。ああ、あなたがするすべてがそれを印刷している場合は、戻り値をconst参照にする必要があります。 –

    +0

    あなたは 'std :: setw'のようなものを探しているかもしれませんが、とにかく効率の差はありそうにありません。 –

    答えて

    2

    文字列は、文字列がローカルであることで、ヴァル

    返され、その値によって返す唯一のオプションですので、関数は、それほど効果的ではないことは明らかです。実際には関数の効率が悪くなるという値による戻り値ではなく、すべての呼び出しで新しい文字列を作成するということです。あなたが価値あるものに戻らなければならないという事実は、単にそのデザインの症状です。しかし、n(呼び出し元が同じnを使用している場合は、返された文字列を保持して再利用できる)を使用して、関数をたくさん呼び出すまで、効率の欠如はおそらく僅かです。

    もちろん、文字列への参照を関数に渡し、関数が文字列を変更できるようにして、関数が何度も呼び出された場合に実際にはもっと効率的になる参照を返します。すべての呼び出しで新しい文字列を作成しないようにするため、同じ引数文字列を使用します。しかし、その後、関数の使用をより複雑にし、ひいては悪化させる呼び出しコードでその外部文字列を管理する必要があります。とにかく引数文字列を再利用しないと、これはもはや効率的ではありません。

    すべてのインスタンスで新しい文字列を使用することを選択した場合、関数よりも単純であり(より効率的ですが、文字列を再利用することとの違いよりもわずかにわずかです)単にstd::stringのコンストラクタを使用します。

    outputFile << std::string(data.len(), ' '); 
    

    は全く文字列を作成していないことは、この特定のケースのために、より効率的かもしれません:

    outputFile << std::setfill(' ') << std::setw(data.len()) << ' '; 
    

    ので、一般的な場合のために、選択はつまるところto:効率は素敵なインターフェースより重要であり、文字列を再利用することができます。その後、stringへの参照を渡して変更します。そうでなければ、あなたの例のように新しい文字列を返す方が良いでしょう。あなたが見ることができるように

    +0

    リファレンスを渡すという考えは、おそらく最も効率的なソリューションです。 さらに、std :: stringのコンストラクタを使った2番目のソリューションと同様に、演算子<<にrvalueを渡す方法があるのだろうかと思っていますが、一般的な意味では、固定文字を繰り返したい場合に使用します。 – GoldenSpecOps

    +0

    クラス 'customString'を作成し、文字列を返す適切なコンストラクタとキャスト演算子を実装し、次に提供した2番目のソリューションと同様にそのコンストラクタを使用することができます。私が考えることができる唯一の問題は、キャスト操作によって非効率的になるということですが、確かめるために十分な知識がありません。 – GoldenSpecOps

    +0

    @anonanon関数によって返される値は、* rvalueです。 – user2079303

    0

    string.insert関数を使用できます。関数は文字列の与えられた位置から任意の数の文字を挿入できます。

    文字列& insert(size_t pos、size_t n、char c);

    参照:http://www.cplusplus.com/reference/string/string/insert/

    例:

    string result = "foo"; 
    int n = 5; 
    result.insert(result.length(), n, ' '); //result will become "foo  " 
    
    +0

    実際に私が与えた具体例では非常に良いかもしれませんが、私が言ったように、文字の作成のさまざまなオプションの汎用ソリューションを探しています。 – GoldenSpecOps

    0

    私はあなたの関数は、その非効率的ではないと思います。のは、潜在的な非効率性を点検してみましょう:

    • string::operator+=(char)はひどい見えます(およびカスタムタイプのために、することができます)。しかし、文字列の場合、新しい文字列を作成したり割り当てたりすることはありません。既存の文字列に文字を追加するだけです。 charを追加すると、時間の複雑さが一定になるはずです。実際に文字列内の同じ文字の繰り返しが必要な場合は、user2079303のコンストラクタの提案が実際にそれを作成する正しい方法です。

    • 戻り値によって結果:現代のコンパイラは機能のうち、文字列を移動するかで始まるようにその場でそれを構築し、代わりに一時的なコピーを作成します。文字列の移動も非常に速くなければなりません(特に、ダイナミックメモリが割り当て解除されていない)。

    • 関数が呼び出されるたびに動的に文字列を割り当てます。これは実際には効率的ではない部分です。実際に文字列が必要な場合(そしてあなたの例は単純なイラスト)、user2079303のように既存の文字列への参照を渡すことは、それを解決する良い方法です。いくつかのJava Swing APIは、あなたの例のような短命のオブジェクトに対する動的なメモリ操作を避けるために、既存のオブジェクト参照を受け入れる関数で修正されました。

    文字列の作成を避ける別の方法は、再設計です。コードが実際に出力される場合は、関数への参照をostreamに渡し、関数が最も効率的に何かを出力する方法を決定させる。私が言ったように、それはあなたのユースケースに依存します。

    +1

    最新の(C++ 11準拠の)コンパイラ**は、関数から文字列を移動する必要があります**。たとえpre-C++ 11であっても、NRVOを実装すればコピーを避けることができます(現代のコンパイラは移動を避けます)。 – user2079303

    +0

    @ user2079303説明をありがとう。 –

    +0

    ああ、現代のコンパイラが文字列をコピーするのではなく、文字列を移動することはわかりませんでした。もしそうなら、返り値by関数の初期設定はうまくいくと思います。ありがとうございました – GoldenSpecOps

    0

    は、あなたはそれが複雑になり、あなたのaddspace

    #include <iostream> 
    
    struct secret_thing_to_add_space{ 
        int number; 
    }; 
    
    std::ostream& operator << (std::ostream& os, const secret_thing_to_add_space& s){ 
        //just use simple method here, you can use something different 
        for(int i=0;i<s.number;++i)os<<' '; 
        return os; 
    }; 
    
    secret_thing_to_add_space addspace(int n){ 
        return {n}; 
    } 
    
    int main(){ 
        std::cout<< "begin" << addspace(10) << "end"; 
    } 
    

    になることができ、この場合、あなたのIO操作


    を行うために十分な情報が含まれている何かを返すことができます。

    関連する問題