在C/C++中指针可以说是很重要的一个环节,也是很让人头疼的一个话题.
在正式进入正题之前有以下几个比较琐碎的知识点需要我们了解:
1, Composite pointer
(1), 如果参数比较的两个指针(类型一致)都是没有指向任何对象(null pointer), 那么这两个指针的 composite pointer type为: nullptr(std::nullptr_t);
(2), 如果参与比较的两个指针的类型为:
void* pointer;
type* pointer1;
那么composite pointer type为:
union{ void* pointer, type* pointer1;};
(3), 如果参与比较的两个指针(类型都为 T*)其中一个为null pointer, 那么composite pointer type为: T*;
(4), 如果参与比较的两个指针
$1: int* p1 和 const int* p2 那么composite pointer type为 const int*
$2: struct A{}; struct B : public A{};
A* p1; const B* p2; 最终的composite pointer type为 const A* 和 const B*;
(5), 如果参与比较的两个指针 为class member data:
$1: Type* class::p1; const Type1* class::p2; 最终的composite pointer type为:
const Type* class::p1 和 const Type1* class::p2(即使Type是继承的Type1,反之依然).
For example, the composite pointer type of void* and const int* is const void*. The composite pointer type of int** and const int** is const int* const*. Note that until C++14, int** and const int** could not be compared.
Note that this implies that any pointer can be compared with void*.
1),如果参与比较的两个指针的静态类型相同且指向同一个对象.
此时比较的是: 两个指针的地址.
#include <memory>
#include <iostream>
struct A {
int a{ 10 };
};
struct B {
int b{ 20 };
};
struct AB : public A, public B
{
int ab{ 30 };
};
int main()
{
AB ab1;
AB* ab2{&ab1};
AB* ab3{ &ab1 };
std::cout << "The addressof ab2: " << ab2 << std::endl;
std::cout << "The addressof ab3: " << ab3 << std::endl;
if(ab2 < ab3){
std::cout << "ab2 < ab3" <<std::endl;
}else if(ab2 > ab3){
std::cout << "ab2 > ab3" <<std::endl;
}else if(ab2 == ab3){
std::cout << "ab2 = ab3" <<std::endl;
}
return 0;
}
output:
The addressof ab2: 0x7ffe9628f2e0
The addressof ab3: 0x7ffe9628f2e0
ab2 = ab3
2) 当参与比较的两个指针的静态类型以及所指对象的类型属于同一个继承体系结构中, 且两个指针指向同一个对象,其中一个指针的静态类型与所指对象的静态类型相同的时候.
此时比较的是两个指针是否指向同一个对象.
#include <memory>
#include <iostream>
struct A {
int a{ 0 };
};
struct B {
int b{ 0 };
};
struct AB : public A, public B
{
int ab{ 0 };
};
int main()
{
AB ab1;
AB* ab2{ &ab1 };
B* ab3 {&ab1};
std::cout << "ab2: " << ab2 << std::endl;
std::cout << "ab3: " << ab3 << std::endl;
if (ab2 == ab3)
{
std::cout << "ab2 = ab3" << std::endl;
}else if (ab2 < ab3) {
std::cout << "ab2 < ab3" << std::endl;
}else if (ab2 > ab3) {
std::cout << "ab2 > ab3" << std::endl;
}
return 0;
}
output:
ab2: 00000092089CF708
ab3: 00000092089CF70C
ab2 = ab3
从demo1我们可以看到虽然两个指针的地址不同,但是由于指向同一个对象,且其中一个指针的类型与被指向对象的静态类型一致,那么编译器就会自动给我们做offset.于是还是认为ab2=ab3.
x86-32bit
if((static_cast<long>(ab3)-4)-static_cast<long>(ab2))
3) 如果参与比较的两个指针指向不同的对象,但是这两个对象属于同一个继承体系中, 且其中一个指针的静态类型与两个被指对象的静态相同的时候.
此时比较的是地址.
#include <memory>
#include <iostream>
struct A {
int a{ 0 };
};
struct B {
int b{ 0 };
};
struct AB : public A, public B
{
int ab{ 0 };
};
int main()
{
AB ab1;
AB ab2;
AB* ab3{ &ab1 };
B* ab4 {&ab2};
std::cout << "ab3: " << ab3 << std::endl;
std::cout << "ab4: " << ab4 << std::endl;
if (ab3 == ab4)
{
std::cout << "ab3 = ab4" << std::endl;
}else if (ab3 < ab4) {
std::cout << "ab3 < ab4" << std::endl;
}else if (ab3 > ab4) {
std::cout << "ab3 > ab4" << std::endl;
}
return 0;
}
output:
ab3: 0000003FCDF8FA58
ab4: 0000003FCDF8FA8C
ab3 < ab4
4)如果参与比较的两个指针指向同一个继承体系中的两个不同的对象, 但是这两个参与比较的指针的静态类型没有一个跟被指对象的静态类型相同.
此时是不能比较的.
#include <memory>
#include <iostream>
struct A {
int a{ 0 };
};
struct B {
int b{ 0 };
};
struct AB : public A, public B
{
int ab{ 0 };
};
int main()
{
AB ab1;
AB ab2;
A* ab3{ &ab1 };
B* ab4 {&ab2};
std::cout << "ab3: " << ab3 << std::endl;
std::cout << "ab3: " << ab4 << std::endl;
if (ab3 == ab4) //error! cant not compile
{
std::cout << "ab3 = ab4" << std::endl;
}else if (ab3 < ab4) { //error!
std::cout << "ab3 < ab4" << std::endl;
}else if (ab3 > ab4) { //error!
std::cout << "ab3 > ab4" << std::endl;
}
return 0;
}
5) 如果参与比较的两个指针指向同一个具有继承体系的对象,但是这两个指针的静态类型即使有一个不属于继承体系.
此时是不能进行比较的.
#include <memory>
#include <iostream>
struct A {
int a{ 0 };
};
struct B {
int b{ 0 };
};
struct AB : public A, public B
{
int ab{ 0 };
};
int main()
{
AB ab1;
AB ab2;
AB* ab3{ &ab1 };
int* ab4 {reinterpret_cast<int*>(&ab1)};
std::cout << "ab3: " << ab3 << std::endl;
std::cout << "ab3: " << ab4 << std::endl;
if (ab3 == ab4) //error! cant not compile
{
std::cout << "ab3 = ab4" << std::endl;
}else if (ab3 < ab4) { //error!
std::cout << "ab3 < ab4" << std::endl;
}else if (ab3 > ab4) { //error!
std::cout << "ab3 > ab4" << std::endl;
}
return 0;
}