说明

对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,可以自己写一个,写的时候注意数组

Author : XDU18清欢