5

免責事項:この質問は理解のためのものです。現場で使用boost::lexical_castします。とはいえ、現実の世界ではある種の場所で登場しています。


「インライン」lex-castアプローチで次の試みをしてください。

#include <string>
#include <sstream>
#include <iostream>

int main()
{
    const std::string s = static_cast<std::ostringstream&>(
       std::ostringstream() << "hi" << 0
    ).str();
    std::cout << s;
}

結果はのようなものになります0x804947c0。これは、operator<<"hi"機能するのは、LHSがstd::ostream&をとらなければならない無料の関数であり、一時的std::ostringstream()にref-to-non-にバインドできないためconstです。残っている唯一の一致は、RHS ††operator<<を引き受けるものです。const void*

それでは、オペランドを交換しましょう

#include <string>
#include <sstream>
#include <iostream>

int main()
{
    const std::string s = static_cast<std::ostringstream&>(
       std::ostringstream() << 0 << "hi"
    ).str();
    std::cout << s;
}

結果は"0hi"です。

これはほとんど意味があります。なぜなら、operator<<それはintベースostream†††のメンバー関数であり、そのため、一時的に呼び出されても問題ないからです。その操作の結果は、次がチェーンされているostreamベースへの参照です。つまり、それをとして読み取ります。operator<<(std::ostringstream() << 0) << "hi"

しかし、なぜその操作が"hi"続行されて期待される結果が得られるのでしょうか。LHSの参照はまだ一時的なものではありませんか?


C++03に焦点を当てましょう。最初の例は、右辺値のキャッチオール演算子により、C++11では実際には「意図された」ものとして機能する可能性があると言われています。

[C++03: 27.6.2.1]: template<class charT, class traits> basic_ostream<charT,traits>& operator<<(basic_ostream<charT,traits>&,charT*);

†† [C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(const void* p);

††† [C++03: 27.6.2.1]: basic_ostream<charT,traits>& operator<<(int n);

4

2 に答える 2

3

理由は簡単です。私が尋ねた質問を読んだ場合:

std::ostringstream は、その内容ではなく c-string のアドレスを出力します。

一時的なものではなく「適切な」参照を取得する秘訣は、参照を返すオブジェクトのメソッドを呼び出すことです (何らかの理由で拘束力のない制限に限定されません)。

上記のNawazの回答で、彼std::ostream& std::ostream::flush()はあなたの場合は次のように呼びました:

std::ostringstream() << 0 << "hi"

あなたが呼び出すstd::ostringstream& std::ostringstream::operator<<(int)

同じ結果です。

驚くべき動作は、ostreamごちゃまぜの実装によるものです。一部operator<<はメンバー メソッドであり、他はフリー関数です。

X& ref()オブジェクトにメソッドを実装することで、簡単にテストできます。

struct X { X& ref(); };

void call(X& x);

int main() {
    call(X{});       // error: cannot bind X& to a temporary
    call(X{}.ref()); // OK
}

編集:しかし、X&(の結果ref)が同じように扱われないのはなぜですか?

分類の問題です。一時は でprvalueあり、参照はlvalueです。参照は へのバインドのみが許可されlvalueます。

もちろん、メソッドは on で呼び出すことができrvalue(したがってprvalue)、それらのメソッドは呼び出されたオブジェクトへの参照を返す可能性があるため、ばかげた (1)参照は制限にバインドすることしか許可されていないことを簡単に回避できます...lvalue

rvalue(1) また、a を const-reference にバインドできるという事実とも矛盾しています。

于 2013-01-18T18:34:21.047 に答える
2

LHSの参照はまだ一時的なものではありませんか?

これは一時(戻り値)への左辺値参照であり、それでも左辺値であるため、左辺値参照にバインドできます。

l / rvaluenessではなく、ライフタイムの観点から一時的なものを考えてください。

于 2013-01-18T07:06:20.253 に答える