0

私は次のコードを持っています:

string join(initializer_list<string_view> strings);

initializer_list は std::initializer_list であり、string_view は std::string ビューではありませんが、const string& および const char* からのコンストラクターを持つ非常に類似したクラスです。

次に、次の呼び出しがありjoinます。

EXPECT_EQ("this", join({ string("this") }));

少し調査した結果、結果の初期化子リストの最初の要素が"this"butではないことがわかりました"\0his"。これは、によって作成されたテンポラリのデストラクタが、テンポラリの作成string("this")直後に呼び出されるためですstring_view(したがって、無効なポインタが含まれています)。の寿命がstring("this")完全式の最後まで延長されないのはなぜEXPECT_EQ("this", join({ string("this") }));ですか?

編集

わかりました、あなたが示唆したように、自己完結型の例があります:

#include <iostream>
#include <string>

using namespace std;

class string_view {
public:
    string_view(const string& str)
        : _begin(str.data())
        , _end(str.data() + str.size()) {
    std::cout << "string_view(...)" << std::endl;
    }

    const char* _begin;
    const char* _end;
};

void join(initializer_list<string_view> strings) {
    std::cout << "join(...)" << std::endl;
    for (auto i = 0u; i < 5; ++i) {
        std::cout << int(strings.begin()->_begin[i]) << " " << strings.begin()->_begin[i] << std::endl;
    }
}

int main() {
    join({ string("this") });
    return 0;
}

最後の Visual Studio C++ (Express) でコンパイルされたこのプログラムの出力:

string_view(...)
join(...)
0
104 h
105 i
115 s
0

上記のプログラムはおそらく不正な形式であるため、コンパイラによって異なる場合があります。

デバッガーでの呼び出しの順序を調べたところ、次の順序があります。

main()
    basic_string(const char*)
    string_view(const string&)
    ~basic_string()
    initializer_list(...)
    join(...)

string("this")のコンテンツを関数内で利用できるようにしたいと思いjoinます。`string("this") が前に破棄されるため、そうではありません。

関数がstring("this")呼び出される前に一時文字列のデストラクタが呼び出されるのはなぜですか、つまり、完全な式の終わりまで延長されないのはなぜですか?joinstring("this")join({ string("this") })

4

1 に答える 1

0

ここで起こっていると思われるのは、文字列への参照から initializer_list を構築しているため、initializer_list の構築が完了すると文字列が範囲外になるということです。

文字列が join() 関数のパラメーターではなく、作成した initializer_list のパラメーターであることがわかります。

私の推測では、initializer_list が作成され、文字列が範囲外になり、join() 関数が string_view に含まれる参照を介してデッド文字列にアクセスしようとします。

于 2014-07-05T14:27:30.473 に答える