我理解双重感叹号的作用(或者我认为我理解),但我不确定它是如何在随机对象上定义的。例如,在下面的代码段中:
Assignment *a;
if (!getAssignment(query, a))
return false;
hasSolution = !!a;
if (!a)
return true;
我如何知道双重感叹号会产生什么价值?换句话说,它总是转换为真?假?或者你能为它定义一个行为,比如执行一个方法来确定结果(对象如何知道在这种情况下如何行动)?由于所有这些感叹事件的发生,我对这段代码感到有点困惑。任何解释都表示赞赏。
希望我很清楚并感谢。
答案 0 :(得分:17)
a
是一个指针。在C ++中,nullptr
被定义为无效指针。 !pointer
将nullptr
指针转换为true
,将非nullptr
指针转换为false
。 !boolean
将true
变为false
,将false
变为true
。它会一直有效。
!(!a)
是一种有用的思考方式。
答案 1 :(得分:9)
不要将它视为“双重感叹号”,将其视为两个独立的运算符,一个运行于另一个运算符的结果。
对于所有原始类型,它将“起作用”。 !a
相当于a == 0
,因此!!a
相当于!(a == 0)
,而a != 0
相当于operator !
。
对于用户定义的类型,除非重载{{1}},否则不会编译。但显然,在这种情况下,行为几乎可以是任何事情。
答案 2 :(得分:4)
!!
不是C ++中的单个令牌,只是解析为应用!
运算符两次。
由于a
是指针而不是类类型的对象,因此!
不能重载。如果true
是空指针,则定义为返回a
,否则返回false
。
!
的第二个应用只是否定了第一个!
的结果。
表达式!!a
相当于a != 0
。
答案 3 :(得分:3)
代码非常复杂。实际上,您希望测试getAssigment
方法是否成功以及指定的指针是否为非空。
代码测试虽然是以复杂的方式利用弱类型,而不是试图接受显性和C ++的强类型。因此,它不是惯用的C ++,而是比必要的更难理解。
特别是,不要在C ++中使用!!a
。这是弱类型语言(如JavaScript)中的既定惯用法,用于将值强制转换为布尔类型。但是在C ++中,这通常是不。
由于hasSolution
未定义或使用,因此不清楚代码的作用。但是,我怀疑该代码应该等同于以下内容:
Assignment *a;
return getAssignment(query, a) and a == nullptr;
(在C ++ 11之前,您需要编写0
而不是nullptr
。)
但是,此代码仍然显示错误的设计:为什么a
通过引用传递?为什么不是返回值?更糟糕的是,a
从未使用过,所以没必要。如果确实不需要a
,则应将其完全排除在外。如果有必要,它应该是返回值。换句话说,getAssignment
的原型应该如下:
Assignment* getAssignment(the_type_of_query query);
它应该简单地使用如下:
Assignment* a = getAssignment(query);
此外,我怀疑此代码实际上将内存所有权分配给原始指针a
。在现代C ++中,这是strongly discouraged。要么不使用指针,要么使用智能指针。
答案 4 :(得分:0)
bool result = true;
result = !!result; // result = true, e.g. !result is false, !!result is !false.
答案 5 :(得分:0)
没有" !!"运算符,所以实际上,该语句相当于:
hasSolution =!(!a);
首先,在表达式" a"上调用operator!(),然后在结果上调用另一个运算符!()。就我们的代码而言," a"是指向Assignement的指针。 C ++定义了一个在指针类型上使用operator!()的特殊情况:它返回一个bool,如果指针为null则为true,否则为false。简而言之,与表达式(a == 0)相同。在(!a)的结果上调用运算符!(),这是一个bool,只是恢复结果,即如果(!a)为假则返回true,如果(!a)为真则返回false。
总之,(!! a)返回与(a!= 0)相同的结果。这是因为" a"是一个指针。
答案 6 :(得分:0)
记住双重否定的最简单方法!! a是将a!= 0缩小到1,将a == 0缩小到0。 哪个在布尔上下文(即C ++)中为true或false。