C++ 将std::less与nullptr一起使用
以下代码段中的断言是否始终有效C++ 将std::less与nullptr一起使用,c++,c++11,C++,C++11,以下代码段中的断言是否始终有效 std::less<Object *> lessPtr; Object * o = new Object(); assert(lessPtr (o, nullptr) == false); std::lessPtr; Object*o=新对象(); 断言(lessPtr(o,nullptr)=false); 否,空指针相对于任何非空指针的顺序未指定 如果操作数“指向不是同一对象的成员或同一数组的元素或不同函数的不同对象,或者如果其中只有一个为空”,则
std::less<Object *> lessPtr;
Object * o = new Object();
assert(lessPtr (o, nullptr) == false);
std::lessPtr;
Object*o=新对象();
断言(lessPtr(o,nullptr)=false);
否,空指针相对于任何非空指针的顺序未指定
如果操作数“指向不是同一对象的成员或同一数组的元素或不同函数的不同对象,或者如果其中只有一个为空”,则比较运算符的结果是未指定的
std::less
和friends对此进行了扩展,以指定总顺序,但不指定空指针按该顺序出现的位置。因此可以保证null
始终大于或小于任何给定的非null指针。但是它没有被指定为小于或大于所有非空指针。Introduction
这个问题实际上归结为对指针类型使用小于关系运算符(其中一个操作数是nullptr
)是否会产生“预期”结果;可惜事实并非如此
结果不详
注意:请注意std::less
保证总订单;这意味着,即使结果在使用函数对象时未指定,它也必须在每次调用时产生相同的未指定值
国际标准()怎么说? 5.9p2关系运算符
[expr.rel]
可以比较指向相同类型的对象或函数的指针(指针转换后),结果定义如下:
- 如果同一类型的两个指针
和p
指向同一对象或函数,或者两个指针都指向同一数组的末尾,或者都为空,则q
都产生p=q
和true
都产生pq
false
- 如果同一类型的两个指针
和p
指向不同的对象,而这些对象不是同一对象或同一数组元素的成员,或者指向不同的函数,或者如果其中只有一个指针为空,则q
的结果是未指定的pq
- 如果两个指针递归地指向同一对象的非静态数据成员,或指向此类成员的子对象或数组元素,则如果两个成员具有相同的访问控制(第11条)且其类不是并集,则指向后一个声明成员的指针会比较大
- 如果两个指针指向具有不同访问控制的同一对象的非静态数据成员(第11条),则结果未指定
- 如果两个指针指向同一union对象的非静态数据成员,则它们的比较相等(如果需要,在转换为
之后)。如果两个指针指向同一数组的元素,或者一个指针指向数组末尾以外的元素,则指向下标较高的对象的指针会比较高void*
- 未指定其他指针比较
20.8.5p8
比较[Comparison]
对于模板更大的
、更小的
、更大的
和更小的
,任何指针类型的专门化都会产生一个总顺序,即使内置操作符
,=
没有
那么,标准到底在说什么?
对
p
的判决是什么?因为
p
和q
不指向同一数组的不同元素(包括超过数组最后一个元素的元素),并且都不指向同一对象的非静态数据成员;执行p
(和p>q
)时的结果未指定
这里有一个古老的答案,其中引用了标准中的一句话,即less可能不会像您预期的那样表现为指针:。我怀疑答案是标准并不能保证它,但在实践中应该可以。N3936(C++14)比N3337添加了更强的保证
T * p = new T;
T * q = nullptr;
bool a = p < q; // unspecified
bool b = p < q; // unspecified
assert (a == b); // can fire
std::less<T*> comp;
bool a = comp (p, q); // unspecified
bool b = comp (p, q); // unspecified
assert (a == b); // can not fire