[英]Error: no match for operator << in std::cout (I have already overloaded the << operator)
[英]operator << : std::cout << i << (i << 1);
我在一行中使用了流运算符<<和位移运算符<<。 我有点困惑,为什么代码A)与代码B)不会产生相同的输出?
一种)
int i = 4;
std::cout << i << " " << (i << 1) << std::endl; //4 8
B)
myint m = 4;
std::cout << m << " " << (m << 1) << std::endl; //8 8
类myint:
class myint {
int i;
public:
myint(int ii) {
i = ii;
}
inline myint operator <<(int n){
i = i << n;
return *this;
}
inline operator int(){
return i;
}
};
提前致谢
哎呀
您的第二个示例是未定义的行为。
您已经在myint
类上定义了<<
操作符,就好像它实际上是<<=
。 当您执行i << 1
,在价值i
不被修改,但是当你执行m << 1
,在价值m
被修改。
在C ++中,对变量进行读写(或多次写入)而没有中间顺序点是不确定的行为,就其参数而言,函数调用和运算符都不是中间点。 代码是否不确定
std::cout << m << " " << (m << 1) << std::endl;
将在m
被m << 1
更新之前或之后输出第一个m
。 实际上,您的代码可能会做一些完全奇怪的事情,或者崩溃。 未定义的行为可能导致任何事情,因此请避免使用。
为myint
定义<<
操作符的正确方法myint
是:
myint operator<< (int n) const
{
return myint(this->i << n);
}
( this->
不是严格必需的,只是我重载运算符时的样式)
因为int << X返回一个新的int。 myint << X修改当前的myint。 您的myint <<运算符应固定为前者。
首先获得8的原因是,显然在实现中首先调用m << 1。 该实现可以自由地以任何顺序进行操作。
您的<<运算符实际上是<< =运算符。 如果您用
std::cout << i << " " << (i <<= 1) << std::endl; //8 8
你应该得到8 8。
由于m
是myInt
第二个示例可以重写为:
std::cout << m << " " << (m.operator<<( 1)) << std::endl;
评价的子表达式的顺序m
和(m.operator<<( 1))
是不确定的,所以没有说法,其中“ m
”,你会得到第1'表达的是m
被使用(这是一个简单的m
表达式)。 因此,您可能会得到“ 4 8”的结果,也可能会得到“ 8 8”。
请注意,该语句不会导致未定义的行为,因为在m
修改与“读取”之间存在序列点(至少一个函数调用)。 但是未指定子表达式的求值顺序,因此尽管编译器必须生成结果(它不会崩溃-至少不会合法崩溃),但没有说应该生成两个可能结果中的哪一个。
因此,该语句与具有未定义行为的语句一样有用,也就是说它不是很有用。
那么(m << 1)在m之前被求值,因此m已经持有8,因为在运算符<<中,您覆盖了自己的值。
这是您的错误行为,operator <<应该是const,不能更改您的对象。
因为myint的<<
操作符会修改其lhs。 因此,在计算m << 1
,m实际上将具有值8(而i << 1
仅返回8,但不使i等于8)。 由于未指定m<<1
是否在cout << m
之前执行(因为未指定函数或运算符的参数的评估顺序),因此未指定输出是8 8
还是4 8
。
C ++语言未定义运算符的求值顺序。 它仅定义了它们的关联性。
由于您的结果取决于表达式中何时对operator<<
函数进行求值,因此结果是不确定的。
代数operator $
函数应始终为const
并返回一个新对象:
inline myint operator <<(int n) const { // ensure that "this" doesn't change
return i << n; // implicit conversion: call myint::myint(int)
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.