说明
对c/c++指针的一个总结
PART Ⅰ 指针的声明
1.一个元素的指针
int * p = new int(10);
2.数组的指针
int *p = new int [10];
3.函数指针
#include <bits/stdc++.h> using namespace std; using ll = long long int; void f() { cout << "f" << endl; } int main() { void (*p)() = f; (*p)(); p(); return 0; }
(*p)()是标准写法,p()是简单写法
非常的套路
#include <bits/stdc++.h> using namespace std; using ll = long long int; int* f(int (&arr)[5],double) { cout << "f" << endl; } int main() { int* (*p)(int(&arr)[5],double) = f; int arr[5]; (*p)(arr,double()); return 0; }
4.成员函数指针
静态成员函数
这个等效于限定作用域的普通函数
查了一下,&可加可不加,正常来说不需要加&
ll (*p)(ll) = test::f;
因为c++定义,函数名就是函数的起始地址
#include <bits/stdc++.h> using namespace std; using ll = long long int; struct test { static ll f(ll) { cout << "f" << endl; return 0ll; } }; void wapper(ll (*p)(ll)) { p(10); } int main() { ll (*p)(ll) = &test::f; wapper(p); wapper(&test::f); return 0; }
普通成员函数
成员函数指针的size是普通指针的两倍
也就是实现为8字节的具体函数指针 + 8字节的偏移量
8字节的具体函数指针指向一个带有this指针参数的函数
8字节的偏移量,标志这个对象,的偏移量
因为多继承的时候,会有一个对象布局的情况
没有多继承的时候,这个偏移量是 0
这里有比较奇怪的 .* 和 ->*,专门调用成员函数的运算符
还有优先级的问题,要(obj ->* p)()这样调用
#include <bits/stdc++.h> using namespace std; using ll = long long int; struct test { ll f(ll a,ll b) { cout << "f" << "\n"; return a + b; } }; void wapper(ll (test::*p)(ll,ll)) { test obj; (obj.*p)(1,2); } int main() { auto obj = new test; ll (test::*p)(ll,ll) = test::f; (obj ->* p)(10,10); wapper(p); wapper(test::f); return 0; }
5.模板函数
静态成员函数、成员模板函数类似
#include <bits/stdc++.h> using namespace std; using ll = long long int; template<typename T> void f(T t) { cout << typeid(T).name() << endl; } int main() { void (*p)(ll) = f<ll>; p(10); return 0; }
6.成员变量指针
取静态类成员函数指针的时候,要全局初始化全局变量
否则链接失败
注意普通指针实现为一个地址,而成员变量指针实现为一个偏移量
空成员变量指针的值为-1
这也是为什么成员变量指针需要特殊的操作的原因
#include <bits/stdc++.h> using namespace std; using ll = long long int; struct test { static ll f; ll g; }; ll test::f = 100; // 要做全局初始化,否则,链接失败 int main() { ll *f = &test::f; ll (test::*g) = &test::g; test obj; obj.*g = 10; cout << *f << endl; cout << obj.g << endl; return 0; }
7.待填
多继承,虚基类,虚函数,的各种指针
多继承,虚基类的时候,指针会复杂起来
总结
普通指针就是一个地址,不同的指针类型意味着对内存不同的操作方式,以及做算数运算时不同
为了实现指针的语意,不同的编译器有不同的实现方式
复杂指针的实现具体看编译器
PART Ⅱ 智能指针
1.unique
c++11中没有make_unique,可以自己写一个,写的时候注意数组