3

正しく理解していることを確認したい。以下の C++ 関数では、std::string の 3 つのインスタンスが作成されます。

  • caller() の s1 の 1 つは、割り当てコンストラクターと呼ばれるものを介して
  • コピー コンストラクターを介した callee() 関数の s2 パラメーター用の 1 つ
  • コピー コンストラクターを介した s3 用の 1 つ

私は正しいですか?その場合、3 つのインスタンスはすべて範囲外になるとクリーンアップされますか? 私の理解が正しければ、これが良いコードかどうかを実際に尋ねているわけではありません。

void caller(void) {
    std::string s1 = "hi";
    callee(s1);
}

void callee(std::string s2) {
    std::string s3 = s2;
}
4

2 に答える 2

3

コピーが作成されているように見えるすべての場所でコピーが作成されていると思い込まないでください。実際には、コピー省略は思ったよりも頻繁に発生します。コピーに副作用がある場合でも、コンパイラは余分なコピーを自由に最適化できます。

void caller(void) {
    std::string s1 = "hi";
    //theoretically, s1 is copied here
    //in practice, the compiler will optimize the call away
    functionCallee(s1);
}

void callee(std::string s2) {
    //although s2 is passed by value, it's probably no copy was created
    //most likely, it's exactly the same as s1 from the calling context
    std::string s3 = s2;
}

さらに、メソッドがインラインであり、副作用が発生しないことをコンパイラが検出した場合、文字列作成されないことさえあります。

于 2012-06-03T15:35:14.940 に答える
2

あなたはほとんど正しいです。

3 つまたは 4 つの文字列が作成される可能性があり (の構築が省略されているかどうかによって異なりますs1)、それぞれの場合にそれらを構築するためにコンストラクターが呼び出されます。見た目にも関わらず、代入演算子への呼び出しはありません。

void caller(void) {
    //A temporary std::string is constructed with the
    //basic_string(const CharT* s, const Allocator& alloc = Allocator())
    //constructor.
    //(In the call, `s` is initialized to point to the first element of "hi".)
    //This temporary is then move constructed in to s1.
    //The move constructor is
    //basic_string(basic_string&& other)
    //This move construction may be elided.
    std::string s1 = "hi"; //At the end of the full expression (ie, at the semicolon)
                           //the lifetime of the temporary string ends (unless
                           //the construction of s1 is elided, in which
                           //case the temporary becomes s1, and its lifetime ends
                           //with s1).
    //s2 is copy constructed from s1
    //The copy constructor is
    //basic_string(const basic_string& other)
    callee(s1);
    //the lifetime of s1 ends
}

void callee(std::string s2) {
    //s3 is copy constructed from s2
    std::string s3 = s2;
    //the lifetime of s3 ends
    //the lifetime of s2 ends
}
于 2012-06-03T15:49:00.767 に答える