涉及的临时运算符重载决策订单
-
20-09-2019 - |
题
考虑以下最小示例:
#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