简体   繁体   English

运算符<<:std :: cout << i <<(i << 1);

[英]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 . 将在mm << 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: 由于mmyInt第二个示例可以重写为:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM