[英]operator << : std::cout << i << (i << 1);
I use the stream operator << and the bit shifting operator << in one line. 我在一行中使用了流运算符<<和位移运算符<<。 I am a bit confused, why does code A) not produce the same output than code B)? 我有点困惑,为什么代码A)与代码B)不会产生相同的输出?
A) 一种)
int i = 4;
std::cout << i << " " << (i << 1) << std::endl; //4 8
B) B)
myint m = 4;
std::cout << m << " " << (m << 1) << std::endl; //8 8
class myint: 类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;
}
};
thanks in advance 提前致谢
Oops 哎呀
Your second example is undefined behavior. 您的第二个示例是未定义的行为。
You have defined the <<
operator on your myint
class as if it were actually <<=
. 您已经在myint
类上定义了<<
操作符,就好像它实际上是<<=
。 When you execute i << 1
, the value in i
is not modified, but when you execute m << 1
, the value in m
is modified. 当您执行i << 1
,在价值i
不被修改,但是当你执行m << 1
,在价值m
被修改。
In C++, it is undefined behavior to both read and write (or write more than once) to a variable without an intervening sequence point, which function calls and operators are not, with respect to their arguments. 在C ++中,对变量进行读写(或多次写入)而没有中间顺序点是不确定的行为,就其参数而言,函数调用和运算符都不是中间点。 It is nondeterministic whether the code 代码是否不确定
std::cout << m << " " << (m << 1) << std::endl;
will output the first m
before or after m
is updated by m << 1
. 将在m
被m << 1
更新之前或之后输出第一个m
。 In fact, your code may do something totally bizarre, or crash. 实际上,您的代码可能会做一些完全奇怪的事情,或者崩溃。 Undefined behavior can lead to literally anything, so avoid it. 未定义的行为可能导致任何事情,因此请避免使用。
One of the proper ways to define the <<
operator for myint
is: 为myint
定义<<
操作符的正确方法myint
是:
myint operator<< (int n) const
{
return myint(this->i << n);
}
(the this->
is not strictly necessary, just my style when I overload operators) ( this->
不是严格必需的,只是我重载运算符时的样式)
Because int << X returns a new int. 因为int << X返回一个新的int。 myint << X modifies the current myint. myint << X修改当前的myint。 Your myint << operator should be fixed to do the former. 您的myint <<运算符应固定为前者。
The reason you're getting 8 for the first is that apparently m << 1 is called first in your implementation. 首先获得8的原因是,显然在实现中首先调用m << 1。 The implementation is free to do them in any order. 该实现可以自由地以任何顺序进行操作。
Your << operator is in fact a <<= operator. 您的<<运算符实际上是<< =运算符。 If you replace the line with 如果您用
std::cout << i << " " << (i <<= 1) << std::endl; //8 8
you should get 8 8. 你应该得到8 8。
since m
is a myInt
your second example could be rewritten as: 由于m
是myInt
第二个示例可以重写为:
std::cout << m << " " << (m.operator<<( 1)) << std::endl;
The order of evaluation for the subexpressions m
and (m.operator<<( 1))
is unspecified, so there's no saying which " m
" you'll get for the 1'st expression that m
is used in (which is a simple m
expression). 评价的子表达式的顺序m
和(m.operator<<( 1))
是不确定的,所以没有说法,其中“ m
”,你会得到第1'表达的是m
被使用(这是一个简单的m
表达式)。 So you might get a result of "4 8" or you might get "8 8". 因此,您可能会得到“ 4 8”的结果,也可能会得到“ 8 8”。
Note that the statement doesn't result in undefined behavior because there are sequence points (at least one function call) between when m
is modified and when it's 'read'. 请注意,该语句不会导致未定义的行为,因为在m
修改与“读取”之间存在序列点(至少一个函数调用)。 But the order of evaluation of the subexpressions is unspecified, so while the compiler has to produce a result (it can't crash - at least not legitimately), there's no saying which of the two possible results it should produce. 但是未指定子表达式的求值顺序,因此尽管编译器必须生成结果(它不会崩溃-至少不会合法崩溃),但没有说应该生成两个可能结果中的哪一个。
So the statement is about as useful as one that has undefined behavior, which is to say it's not very useful. 因此,该语句与具有未定义行为的语句一样有用,也就是说它不是很有用。
Well (m << 1) is evaluated before m and therefore m holds 8 already, as in your operator<< you overwrite your own value. 那么(m << 1)在m之前被求值,因此m已经持有8,因为在运算符<<中,您覆盖了自己的值。
This is wrong behaviour on your side, the operator<< should be const and not change your object. 这是您的错误行为,operator <<应该是const,不能更改您的对象。
Because the <<
operator of myint modifies its lhs. 因为myint的<<
操作符会修改其lhs。 So after evaluating m << 1
, m will actually have the value 8 (while i << 1
only returns 8, but does not make i equal to 8). 因此,在计算m << 1
,m实际上将具有值8(而i << 1
仅返回8,但不使i等于8)。 Since it is not specified whether m<<1
executes before cout << m
(because it's not specified in which order the arguments of a function or operator are evaluated), it is not specified whether the output will be 8 8
or 4 8
. 由于未指定m<<1
是否在cout << m
之前执行(因为未指定函数或运算符的参数的评估顺序),因此未指定输出是8 8
还是4 8
。
The C++ language does not define the order of evaluation of operators. C ++语言未定义运算符的求值顺序。 It only defines their associativity. 它仅定义了它们的关联性。
Since your results depend on when the operator<<
function is evaluated within the expression, the results are undefined. 由于您的结果取决于表达式中何时对operator<<
函数进行求值,因此结果是不确定的。
Algebraic operator $
functions should always be const
and return a new object: 代数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.