5

C++ の経験がある人なら簡単に答えられると思われる質問がいくつかあります。TL;DR の質問は太字にします。

次のコードがあるとします。

void stringTest(const std::string &s)
{
    std::cout << s << std::endl;
}

int main()
{
    stringTest("HelloWorld");
}

うまくいけば、誰かがここで私の思考プロセスの誤りを指摘できます:

C スタイルの文字列を渡すときに、stringTest のパラメーターを const とマークする必要があるのはなぜですか? その cstyle 文字列コンストラクターを使用して行われる std::string への暗黙的な変換はありません。したがって、「s」はリテラルへの参照ではなくなります (const である必要はありません)。

さらに、 cstyle 文字列コンストラクターはどのように見えるでしょうか? また、コンパイラーは を見てこれを呼び出すことをどのように認識していますか?

stringTest("HelloWorld");

文字列リテラルを単に char* のようなものとして認識しますか?

コピー コンストラクターを研究しているときに、これらの質問に出くわしました。私自身の明確化のための別の簡単な質問...

次のような場合:

std::string s = "HelloWorld";

cstyle 文字列コンストラクターを使用して一時的な std::string をインスタンス化し、文字列コピー コンストラクターを使用して一時的な文字列を "s" にコピーしますか? :

std::string(const std::string&);
4

4 に答える 4

2

C スタイルの文字列を渡すときに、stringTest のパラメーターを const とマークする必要があるのはなぜですか?

パラメーターが参照である場合にのみ必要です。一時的なものは渡されstd::stringたものから構築され、一時的なものへの非参照は違法であるためです。char const*const

文字列リテラルを単に char* のようなものとして認識しますか?

文字列リテラルはchar const配列であり、 に減衰しchar const*ます。それから、コンパイラは非explicitコンストラクタstd::string::string(char const *)を使用して一時を構築する必要があると推測します。

cstyle コンストラクターを使用して一時的な std::string をインスタンス化し、一時的な文字列を文字列コピー コンストラクターを使用して "s" にコピーしますか?

それよりも少し複雑です。はい、一時的に作成されます。ただし、コピー コンストラクターは呼び出される場合と呼び出されない場合があります。コンパイラは、最適化としてコピーの構築をスキップできます。ただし、コピー コンストラクターは引き続き提供する必要があるため、次のコードはコンパイルされません。

class String {
    String(char const *) {}
  private:
    String(String const &);
};

int main()
{
    String s = "";
}

また、C++11 では、move コンストラクターが提供されている場合はそれが使用されます。その場合、コピー コンストラクターは必要ありません。

于 2012-04-11T15:47:52.853 に答える
2

C スタイルの文字列を渡すときに、stringTest のパラメーターを const とマークする必要があるのはなぜですか?

編集:一時的なものは不変でなければなりません。larsmans のコメントと回答を参照してください。彼は正しいです。

単純な理由:

void change(std::string& c) { c = "abc"; }
change("test"); // what should the code exactly do??

さらに、cstyle 文字列コンストラクターはどのように見えるでしょうか。また、コンパイラーは、以下を見てこれを呼び出すことをどのように認識しますか。

コンストラクターstd::stringを検索しますstring(char*)

次のような場合:

std::string s = "HelloWorld";

cstyle コンストラクターを使用して一時的な std::string をインスタンス化し、一時的な文字列を文字列コピー コンストラクターを使用して "s" にコピーしますか?: std::string(const std::string&);

いいえ。この正確なケース ( TYPE variable = SOMETHING) では、書き込みと同じTYPE variable(SOMETHING);です。したがって、コピーは使用されません。

于 2012-04-11T15:50:29.350 に答える
2

文字列リテラルを単に char* のようなものとして認識しますか?

元の質問のこの部分は、私が望んでいたほど明確に答えられませんでした。ただし、残りについてはYossarianの回答を完全に支持します(そして賛成票を投じます)。

基本的に、コード内で文字列リテラルを検出したときにコンパイラが何をしているのかを理解する必要があります。その文字の配列 (C スタイルの文字列が実際にそうであるように) は、実際にはそれが含まれるコードとはまったく異なる場所に格納されます (アーキテクチャによっては、数値リテラルはアセンブリの一部としてその場所自体に格納できます/バイナリ命令)。ここにある 2 つのコード ブロックは、「多かれ少なかれ」同等です (インクルードや名前空間の宣言がないことは無視してください)。

int main(void)
{
    cout << "Hello!" << endl;
    return 0;
}

これは、「実際に」起こっていることに近いです。

const char HELLO_STR[] = { 'H', 'e', 'l', 'l', 'o', '!', 0 };

int main(void)
{
    cout << HELLO_STR << endl;
    return 0;
}

配列の初期化などでエラーが発生した場合はご容赦ください。ただし、これは、文字列リテラルが「実際に」格納されている場所についての意味を表していると思います。これはインラインではありませんが、それが定義されているプログラムの別の部分からは見えない定数です。さらに、一部の (ほとんどの?) コンパイラは、文字列リテラルを「一緒に」配置して、50 か所で同じリテラルを使用している場合、それらの 1 つだけを格納し、それらすべてが同じ定数を参照するようにします。メモリを節約します。

したがって、文字列リテラルを使用するときはいつでも、暗黙のうちに const char* に変換される「目に見えない」場所に存在する const char[N] を使用していることを覚えておいてください。

于 2012-04-11T16:02:22.807 に答える
0

このconst string & s例では、引数「HelloWorld」からコンストラクターを呼び出すために必要です。使用されるコンストラクターは型変換構文です。

sは文字列オブジェクトを直接参照しているため、 Astring& sは実行しません。

型変換は、次のようなものによって定義されます。

 basic_string(const _CharT* __s);

typedefを使用

typedef basic_string<char>    string; 

したがって、宣言は次のように評価されます

basic_string(const char * __s)    
于 2012-04-11T15:49:17.493 に答える