考虑以下最小示例:

#include <iostream>

using namespace std;

class myostream : public ostream {
    public:
        myostream(ostream const &other) :
            ostream(other.rdbuf())
        { }
};

int main() {
    cout << "hello world" << endl;

    myostream s(cout);
    s << "hello world" << endl;

    myostream(cout) << "hello world" << endl;
}

的输出,无论在g ++以及视觉C ++,是

hello world
hello world
0x4012a4

这写入到一个临时对象,myostream(cout)版本,似乎更喜欢代替游离操作者ostream::operator<<(void *)的构件操作者operator<<(ostream &, char *)。这似乎有所作为对象是否具有一个名字。

为什么会出现这种情况?而如何防止这种行为?

修改:为什么正好是现在从各种答案清晰。至于如何避免这种情况,下面似乎有吸引力:

class myostream : public ostream {
    public:
        // ...
        myostream &operator<<(char const *str) {
            std::operator<<(*this, str);
            return *this;
        }
};

然而,这导致在各种模糊度。

有帮助吗?

解决方案

右值不能被结合到非const引用。因此,在您例如临时类型的ostream的不能随意操作的第一个参数<<(标准:: ostream的&,字符常量*)和使用什么是成员的operator <<(无效*)。

如果你需要它,你可以添加一个调用,如

myostream(cout).flush() << "foo";

这将变换右值为参考。

请注意,在C ++ 0X,引进的右值引用将允许操作者提供的过载<<服用rvalue引用作为参数,解决该问题的根本原因。

其他提示

如果一个对象不具有一个名称(即,它是一个暂时的),它不能被结合到非const引用。具体地,它不能被绑定到的第一个参数:

operator<<(ostream &, char *)

我只是意识到部分的答案。临时不是左值,因此它不能被用作类型ostream &的参数。

“我怎样才能使这项工作”的问题依然存在......

由于没有一个答案到目前为止似乎以得到干净的解决方案,我将满足于脏溶液:

myostream operator<<(myostream stream, char const *str) {
    std::operator<<(stream, str);
    return stream;
}

这是唯一可能的,因为myostream具有拷贝构造。 (在内部,它是由一个参考计数std::stringbuf支持。)

虽然C ++ 11日以来有右值引用不解决这个问题,我认为这可能是一种解决办法是预先C ++ 11。

的解决方案是有一个成员函数<<运算,我们可以转换为一个非const参照基类:

class myostream : public ostream {
    public:
        // ...
        template<typename T>
        ostream &operator<<(const T &t) {
            //now the first operand is no longer a temporary,
            //so the non-member operators will overload correctly
            return static_cast<ostream &>(*this) << t;
        }
};

好了,我不知道这会导致对C ++规范,但很容易苏斯了为什么它会发生。

在堆栈上的临时的生活,通常要传递给另一个功能或具有称为在其上的单个操作。所以,如果你拨打免费操作就可以了:

运算符<<(myostream(COUT))

它是在该操作的结束和第二个“<<”操作符来追加ENDL将引用无效目标破坏。从自由“<<”操作符的返回值将是一个遭到破坏的临时对象的引用。 C ++的规格可能定义有关自由经营的规则,以防止沮丧和混乱的C ++程序员这种情况。

现在,在对临时一个“<<(无效*)”算子构件的情况下,返回值是对象本身,这是在堆栈上仍然与不被破坏,所以编译器知道不破坏它而是将其传递到下一个成员运算符,所述一个,是以ENDL。操作者链接的临时上为简洁C ++代码是有用的特征,所以我确信C ++规范设计者考虑它和实施编译器有意支持它。

修改

有人说,它是具有非const引用做。此代码编译:

#include <iostream>
using namespace std;
class myostream : public ostream { 
    public: 
        myostream(ostream const &other) : 
            ostream(other.rdbuf()) 
        { } 
            ~myostream() { cout << " destructing "; }
    }; 
int _tmain(int argc, _TCHAR* argv[])
{
    basic_ostream<char>& result = std::operator << (myostream(cout), "This works");
    std::operator << (result, "illegal");
         return 0;
}

和它返回

  This works destructing illegal
许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top