智能指针

在C++中有智能指针这个概念,智能指针区别于普通的指针,智能指针虽然名字里面有指针两个字,但是却不是指针,指针在C里面是一个特殊类型的变量,这类变量的存储空间与机器字长有关,是用来存放地址的。智能指针是一个泛型类,主要包括auto_prtunique_ptrshared_prt这三个类。这三个类的应用场景不太一样,但都提供了一个能力–行为类似于指针,能在合适的时机释放内部指针占用的内存。使用智能指针,不再需要手动调用析构函数。

智能指针实现主要借助了以下特性:

  1. 栈能够自动管理内存,函数的调用与结束都伴随着入栈出栈
  2. C++提供了运算符重载,指针用到的操作符主要是->*

这三个模版类都在声明在memory这个头文件里面。
初始化智能指针对象时,推荐使用这种形式unique_ptr<T> ptr = make_unique<T>(...args);, T是类型,...args表示调用T的某个构造函数传入的参数。这样的风格可以和JAVA编程风格基本保持一致。智能指针的使用与普通指针类似,每个指针都有不同的类型,每种不同的类型能够访问不同的成员,调用相应的函数,智能指针要实现这个功能,调用泛型类的方法而不产生语法错误,最好的办法就是通过内部保存的原始指针,在别的不提供运算符重载的语言中一般通过消息转发实现,例如Objective-C中的NSProxy, 考虑到指针最常使用的操作符一般是->*+-以及++--, 加减这类操作符一般在数组中使用的比较多,其他情况下, ->*比较常见, 源代码重载了这些操作符.

其中->运算符比较特殊,只能由成员函数重载,此外->返回一个指针或者类的对象。如果返回的是一个指针,会继续调用->运算符,比如p->m,如果重载了p对应类(一般情况下类没有->运算符, 只有指针才有)的->运算符,返回的是一个指针, 那么重载后替换成的方法调用如下(p.operator->())->m.

注意⚠️,重载类的->运算符, 不要使用指针去调用, 重载的是类的, 不是对应指针类型的.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
// Human.hpp
#ifndef Human_hpp
#define Human_hpp

#include <stdio.h>
#include <string>

using namespace std;

class Human {

private:
string name;
int age;

public:
Human(string name, int age);
Human();
~Human();
string getName();
int getAge();
void setName(string name);
void setAge(int age);
void resume();

bool operator>(const Human & other) const {
printf("%d > %d", age, other.age);
return age > other.age;
}

bool operator==(const Human & other) const;
};

#endif /* Human_hpp */
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Human.cpp
#include "Human.hpp"

int Human::getAge() {
return this->age;
}

string Human::getName() {
return this->name;
}

void Human::setAge(int age) {
this->age = age;
}

void Human::setName(string name) {
this->name = name;
}

void Human::resume() {
printf("Name: %s, Age: %d\n", name.c_str(), age);
}

Human::Human(string name, int age) {
this->name = name;
this->age = age;
}

Human::Human() {

}

Human::~Human() {
printf("clean person(%s)\n", name.c_str());
printf("make some clean work!\n");
}

bool Human::operator==(const Human & other) const {
return age == other.age && (strcmp(name.c_str(), other.name.c_str()) == 0);
}
1
2
3
4
5
6
int main() {
Human *human1 = new Human("pinkman", 27);
Human *human2 = new Human("white", 47);
printf("*human1 > *human2 ? %s\n", *human1 > *human2 ? "YES" : "NO");
return 0;
}