operator <<:std :: cout << i <<(i << 1);
我在一行中使用流操作符< <和位移操作符< <。 我有点困惑,为什么代码A)不会产生与代码B相同的输出)?operator <<:std :: cout << i <<(i << 1);
A)
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
类敏:
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
由m << 1
更新。事实上,你的代码可能会做一些奇怪的事情,或者崩溃。未定义的行为可能导致字面上的任何事情,所以避免它。
一个适当的方法来定义<<
运营商myint
是:
myint operator<< (int n) const
{
return myint(this->i << n);
}
(该this->
不是绝对必要的,只是我的风格,当我重载运算符)
但是重载操作符是函数调用,有许多序列点。 – 2010-04-21 21:20:15
'std :: cout 2010-04-21 21:23:14
也许你应该更新你的答案,因为没有你的评论中的解释,很明显,许多顺序点都不能保证关键表达式之间没有一个。 – 2010-04-21 21:29:56
你< <运营商其实是一个运营商。如果您更换
std::cout << i << " " << (i <<= 1) << std::endl; //8 8
行,你应该得到8 8
你已经强调了这个问题,但你的“答案”有未定义的行为 – 2010-04-21 21:18:32
嘛(M < < 1)M前进行评估,因而,M拥有8已经如您在操作< <你覆盖你自己的价值。
这是你身边的错误行为,运营商< <应该是const并且不能改变你的对象。
因为int < < X返回一个新的int。 myint < < X修改当前的myint。你的myint < <运营商应该固定做前者。
你第一次得到8的原因很明显是你的实现中首先调用1。实现可以以任意顺序自由执行。
因为<<
运营商myint修改了它的lhs。因此,在评估m << 1
后,m实际上将具有值8(而i << 1
仅返回8,但不会使我等于8)。由于没有指定m<<1
是否在cout << m
之前执行(因为未指定函数或操作符的参数以何种顺序进行评估),因此未指定输出是8 8
还是4 8
。
因为m
是myInt
你的第二个例子可以写成:
std::cout << m << " " << (m.operator<<(1)) << std::endl;
评价的子表达式的顺序m
和(m.operator<<(1))
是不确定的,所以没有说法,其中“m
”你会得到在m
中使用的第1个表达式(这是一个简单的m
表达式)。所以你可能会得到“4 8”的结果,或者你可能会得到“8 8”。
请注意,语句不会导致未定义的行为,因为在修改m
和“读取”之间存在序列点(至少一个函数调用)。但是子表达式的评估顺序没有指定,所以编译器必须产生一个结果(它不会崩溃 - 至少不合法),但是没有说明应该产生两种可能的结果中的哪一种。
因此,该声明与未定义行为一样有用,也就是说它不是非常有用。
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)
}
几乎重复的:http://stackoverflow.com/questions/2603312/the-result-of-int-c0- coutcc /。对于大多数实际用途来说,它们是相同的,尽管使用“++”而不是“ 2010-04-21 21:19:35
@Jerry Coffin:它们非常相似,但有整个“vs 2010-04-21 21:23:50