1

私はいくつかのC ++を学ぼうとしています。まず、コンソールへの出力とコンソールからの読み取りを処理するいくつかのメソッドを作成しました。コードでマークされている 2 つの大きな問題があり、参照によって渡された文字列の std::vector 内の値を操作/アクセスしています。

以下のメソッドは、ユーザーに尋ねる質問 (std 文字列) と、受け入れられると見なされるユーザーからの応答を含むベクター std 文字列を受け取ります。また、学習のために、ベクトル内の文字列にアクセスしてその値を変更したいと考えました。

std::string My_Namespace::My_Class::ask(std::string question, std::vector<std::string> *validInputs){
    bool val = false;
    std::string response;
    while(!val){
        //Ask and get a response
        response = ask(question);
        //Iterate through the acceptable responses looking for a match
        for(unsigned int i = 0; i < validInputs->size(); i++){
            if(response == validInputs->at(i)){
                ////1) Above condition always returns true/////
                val = true;
                break;
            }
        }
    }
//////////2) does not print anything//////////
println(validInputs->at(0)); //note the println method is just cout << param << "\n" << std::endl
//Really I want to manipulate its value (not the pointer the actual value)
//So I'd want something analogous to validInputs.set(index, newVal); from java
///////////////////////////////////////////
}

追加の質問:

3) ベクトルで .at(index) を使用して値を取得していますが、代わりに [] を使用する必要があることを読みましたが、それがどのように見えるかわかりません (validInputs[i] はしません'コンパイルしないでください)。

4)ディープコピーは不要なので、上記のようにベクターへのポインターを渡すことをお勧めしますが、誰かがそれを確認できますか?

5) ループでは ++i の方が i++ よりも優れていると聞きましたが、本当ですか? なぜ?

4

4 に答える 4

2

3)この場合at、 andを使用しても大きな違いはないはずです。operator[]ベクトル (またはベクトルへの参照) ではなく、ベクトルへのポインターがあることに注意してください。そのため、(*validInputs)[i]またはvalidInputs->operator[](i)演算子のオーバーロードを使用する必要があります。validInputs->at(i)これらの他のアプローチのいずれも使用したくない場合は、使用しても問題ありません。(at引数が配列の境界外にある場合、メソッドは例外をスローしますが、引数が配列の境界外にあるoperator[]場合、メソッドは未定義の動作をします。境界チェックをスキップするため、事実operator[]わかっている場合は高速です。ベクトルの境界内。よくわからない場合は、 を使用して、例外をキャッチする準備をしてください。)iat

4) ポインターは良いですが、参照の方が良いでしょう。また、メソッドでベクトルを変更していない場合は、定数ベクトルへの参照が最適です ( std::vector<std::string> const &)。これにより、null ポインターを渡すことができなくなり (参照を null にすることはできません)、ベクトルを誤って変更することもなくなります。

5) 通常はそうです。 i++これは、元の値をコピーする必要があることを意味し、次にiインクリメントして元の値のコピーを返します。 ++iインクリメントiしてから を返すiため、特に複雑なイテレータを扱う場合は通常は高速です。を使用するunsigned intと、コンパイラは事前インクリメントが問題ないことを理解するのに十分スマートである++i必要がありますが、元のインクリメントされていない の値が必要ない場合は、 の使用を実践することをお勧めしますi

于 2013-01-18T19:56:10.990 に答える
2

const への参照を使用しますstd::find。また、参照によって文字列を取得することに注意してください (それ以外の場合はディープ コピーされます)。

std::string My_Class::
ask (const std::string& question, const std::vector<std::string>& validInputs)
{
    for (;;) {
        auto response = ask (question);
        auto i = std::find (validInputs.begin (), validInputs.end (), response);

        if (i != validInputs.end ()) {
             std::cout << *i << '\n'; // Prints the value found
             return *i;
        }
    }
}

コードを理解していない場合は、反復子について読んでください。もちろん、他にも質問があれば遠慮なく聞いてください。

于 2013-01-18T20:00:28.963 に答える
1

ポイント 1 と 2 については説明しません。なぜなら、あなたが何をしているのかわからないし、askとのコードも見えないからprintlnです。

ベクトルで .at(index) を使用して値を取得していますが、代わりに [] を使用する必要があることを読みましたが、それがどのように見えるかわかりません (validInputs[i] はコンパイルされません) )。

添字アクセスとatメンバー関数は別物です。それらはインデックス付き要素への参照というまったく同じものを提供しますが、範囲外のインデックスを渡すと動作が異なります。at例外がスローされる一方で、[]未定義の動作が呼び出されます (組み込み配列のように)。ポインターでの使用[]はやや醜い(*validInputs)[i]ですが、可能な場合はポインターを避ける必要があります。

ディープコピーは不要なので、上記のようにベクターへのポインターを渡すことをお勧めしますが、誰かがそれを確認できますか?

ディープ コピーは不要ですが、ポインタも不要です。代わりに参照constが必要です。これらを変更するべきではないと思われるため、参照が必要です。

ask(std::string const& question, std::vector<std::string> const& validInputs)

ループでは ++i の方が i++ よりも優れていると聞きましたが、本当ですか? なぜ?

一般的な場合に当てはまります。2 つの操作は異なり、++iインクリメントiして新しい値を返しますが、i++インクリメントi前の値を返します。これには、一時的に保持して返す必要があります。s の場合int、これはほとんど問題になりませんが、太る可能性があるイテレータの場合は、戻り値を必要としない、または気にしない場合は、プリインクリメントの方が効率的であり、より良い選択です。

于 2013-01-18T20:01:09.717 に答える
0

質問 1 と 2 に答えるには、次のような情報がさらに必要になるでしょう。質問のソースは?

3) 最初にポインターを逆参照してから、ベクトルにインデックスを付けます。

(*validInputs)[i]

4) 参考文献はより良いスタイルと見なされます。特に、NULL になることのないポインターの代わりに。

5) 整数の場合は問題ありません (式の結果を評価しない限り)。オーバーロードされた ++ 演算子 (反復子など) を使用する他のオブジェクトについては、++i を使用する方がよい場合があります。しかし実際には、++ 演算子のインライン定義については、おそらく同じコードに最適化されます。

于 2013-01-18T20:00:13.927 に答える