C++ 在哪种情况下,如果(a=b)是个好主意?
可能重复:C++ 在哪种情况下,如果(a=b)是个好主意?,c++,c,C++,C,可能重复: C++编译器通过您编写的警告让您知道 if( a = b ) { //... 这可能是个错误,你肯定想写 if( a == b ) { //... 但是,是否有这样一种情况,即警告应该被忽略,因为它是使用此“功能”的好方法? 我看不出任何代码清晰的原因,所以它是否有用 while ( (line = readNextLine()) != EOF) { processLine(); } 这当然是最简单的例子,很多时候这是有用的。首先要记住的是,(a=true)返回tru
C++编译器通过您编写的警告让您知道
if( a = b ) { //...
这可能是个错误,你肯定想写
if( a == b ) { //...
但是,是否有这样一种情况,即警告应该被忽略,因为它是使用此“功能”的好方法?
我看不出任何代码清晰的原因,所以它是否有用
while ( (line = readNextLine()) != EOF) {
processLine();
}
这当然是最简单的例子,很多时候这是有用的。首先要记住的是,(a=true)返回true,就像(a=false)返回false一样。两个可能的原因:
void some( int b ) {
int a = 0;
if( a = b ) {
// or do something with a
// knowing that is not 0
}
// b remains the same
}
if( NULL = b ) // won't compile because it is illegal
// to assign a value to r-values.
=
运算符(未重写时)通常返回其指定的值。这是为了允许诸如a=b=c=3
之类的语句。在您的问题中,它还允许您执行以下操作:
bool global;//a global variable
//a function
int foo(bool x){
//assign the value of x to global
//if x is equal to true, return 4
if (global=x)
return 4;
//otherwise return 3
return 3;
}
…相当于但短于:
bool global;//a global variable
//a function
int foo(bool x){
//assign the value of x to global
global=x;
//if x is equal to true, return 4
if (global==true)
return 4;
//otherwise return 3
return 3;
}
此外,还应注意(正如Billy ONeal在下面的注释中所述),=
运算符的左参数实际上是一个具有指定类型的类,该类型可以强制(隐式转换)为bool时,这也可以起作用。换句话说,(a=b)
将求值为true
或false
,前提是a属于可以强制为布尔值的类型
因此,除了=
的左手参数是一个对象而不是bool之外,以下情况与上述情况类似:
#include <iostream>
using namespace std;
class Foo {
public:
operator bool (){ return true; }
Foo(){}
};
int main(){
Foo a;
Foo b;
if (a=b)
cout<<"true";
else
cout<<"false";
}
//output: true
这里,a
必须是一个对象,b
必须是一个正确的类型,这是由=
操作符覆盖a
类型的对象定义的。要了解更多关于运算符重写的内容,请参阅维基百科文章,其中包含C++实例:直截了当地说,作为个人观点,我真的不认为这是一个好主意 我的意思是,我知道使用这种语法可以避免在代码中增加一行,但我认为它会降低代码的可读性 这种语法对于@Steven Schlansker建议的语法非常有用,但直接将其用作条件并不是一个好主意 只要我的两分钱 但是有没有一种情况是警告 应该被忽略,因为它是一个好的 如何使用此“功能”?我不明白 任何代码清晰的原因都是可能的 有没有一个案例说明它有用
while ( (line = readNextLine()) != EOF) {
processLine();
}
可以通过在指定周围加上括号来抑制警告。这在某种程度上澄清了程序员的意图。我见过的与(a=b)情况直接匹配的常见情况如下:
if ( (a = expression_with_zero_for_failure) )
{
// do something with 'a' to avoid having to reevaluate
// 'expression_with_zero_for_failure' (might be a function call, e.g.)
}
else if ( (a = expression2_with_zero_for_failure) )
{
// do something with 'a' to avoid having to reevaluate
// 'expression2_with_zero_for_failure'
}
// etc.
关于编写这种代码是否有用,足以证明初学者(有时甚至是专业人员在最坏的时刻)遇到C++时遇到的常见错误,这很难说。这是继承自C和Stroustrup的遗产,而其他一些对C++设计的贡献可能是完全不同的,更安全的路线,如果他们没有试图使C++与C兼容,那么就可以了。
我个人认为这不值得。我在一个团队中工作,以前曾多次遇到此错误。我本来会赞成不允许它(至少需要括号或其他明确的语法,否则它被视为构建错误),以减轻遇到这些错误的负担。这是C语言基本特性的结果: 赋值操作的值就是赋值本身 您可以使用该“返回值”作为
if()
语句的条件,这是偶然的
顺便说一句,这是同样的技巧,让这种疯狂的简洁:
void strcpy(char *s, char *t)
{
while( *s++ = *t++ );
}
当然,当到达t
中的null字符时,while将退出,但同时它将被复制到目标s
字符串
这是否是一个好主意,通常不是,因为它会降低代码可读性并容易出错。您可以使用它来测试函数是否返回任何错误
if (error_no = some_function(...)) {
//handle error
}
假设某个函数在出现错误时返回错误代码,否则返回零
注意,这个答案是关于C++的(我在写了“C”)之前开始写这个答案。 然而,在阅读了延斯·古斯特德的评论后,我意识到这不是我第一次写这样的答案。事实上,这个问题是另一个问题的翻版,对此我给出了以下答案:
所以,我会无耻地在这里引用我自己的话来补充一个重要信息:如果
不是关于比较的。这是关于评估的
这种差异非常重要,因为它意味着只要可以计算为布尔值,if
的括号内就可以有任何内容。这是件好事
现在,通过禁止所有其他操作员都有权使用的=
来限制该语言是该语言的一个危险的例外,这种例外的使用还远远不能确定,而且其缺点确实很多
对于那些不容易使用=
打字错误的人,还有一些解决方案(请参见下面的备选方案…)
问题是你把问题颠倒过来了。“if”表示法并不像在其他语言中那样比较两个值
C/C++if
指令等待任何将计算为布尔值或空/非空值的表达式。此表达式可以包括两个值的比较,和/或可能更复杂
例如,您可以有:
if(i >> 3)
{
std::cout << "i is less than 8" << std::endl
}
允许用户在if中声明并使用p。它是一种语法糖。。。但是很有趣。例如,假设有一个类似XML DOM的对象,其类型在运行时之前是未知的,您需要使用RTTI:
void foo(Node * p_p)
{
if(BodyNode * p = dynamic_cast<BodyNode *>(p_p))
{
// this is a <body> node
}
else if(SpanNode * p = dynamic_cast<SpanNode *>(p_p))
{
// this is a <span> node
}
else if(DivNode * p = dynamic_cast<DivNode *>(p_p))
{
// this is a <div> node
}
// etc.
}
在C++中,你也可以做到这一点。我脑子里没有确切的代码(也没有确切的DDJ文章)
void foo(Node * p_p)
{
if(BodyNode * p = dynamic_cast<BodyNode *>(p_p))
{
// this is a <body> node
}
else if(SpanNode * p = dynamic_cast<SpanNode *>(p_p))
{
// this is a <span> node
}
else if(DivNode * p = dynamic_cast<DivNode *>(p_p))
{
// this is a <div> node
}
// etc.
}
synchronized(p)
{
// Now, the Java code is synchronized using p as a mutex
}
#define synchronized(lock) \
if (auto_lock lock_##__LINE__(lock))
synchronized(p)
{
// Now, the C++ code is synchronized using p as a mutex
}
if( NULL = b ) // won't compile because it is illegal
// to assign a value to r-values.
const T a ;
// etc.
if( a = b ) // Won't compile because it is illegal
// to modify a constant object
void foo()
{
// some code
LOCK(mutex)
{
// some code protected by a mutex
}
FOREACH(char c, MyVectorOfChar)
{
// using c
}
}
#define EQUALS ==
#define ARE_EQUALS(lhs,rhs) (lhs == rhs)
int main(int argc, char* argv[])
{
int a = 25 ;
double b = 25 ;
if(a EQUALS b)
std::cout << "equals" << std::endl ;
else
std::cout << "NOT equals" << std::endl ;
if(ARE_EQUALS(a, b))
std::cout << "equals" << std::endl ;
else
std::cout << "NOT equals" << std::endl ;
return 0 ;
}
if( (a = b) != 0 ) {
...
}
a = b;
if( a != 0 ) {
...
}
do {
...
} while (current = current->next);
if ((fp = fopen("filename.txt", "wt")) != NULL) {
// do something with fp
}
RegEx r;
if(((r = new RegEx("\w*)).IsMatch()) {
// ... do something here
}
else if((r = new RegEx("\d*")).IsMatch()) {
// ... do something here
}
int i = 0;
if((i = 1) == 1) {
// 1 is equal to i that was assigned to a int value 1
}
else {
// ?
}
if (CComQIPtr<DerivedClassA> a = BaseClassPtr)
{
...
}
else if (CComQIPtr<DerivedClassB> b = BaseClassPtr)
{
...
}