引言
实际开发中遇到的问题,将问题简化如下:
- 在外部定义一个空指针
- 将该空指针
值传递
进A函数中,在A函数中赋值 - 赋值完以后,需要在B函数中使用该指针,但该指针却是
空的
上面的说法可能不够准确,直接看实际的例子吧
#include <iostream>
#include <string>
#include <list>
#include <vector>
using namespace std;
class Person
{
public:
Person(const string name, const int age, const int gender)
:m_name(name), m_age(age), m_gender(gender)
{
cout << "call constructor." << endl;
};
~Person() { cout << "call deconstructor." << endl; };
void printPersonInfo();
private:
string m_name;
int m_age;
int m_gender;
};
void Person::printPersonInfo()
{
cout << "name:" << m_name << ", age:" << m_age << ", gender:" << (m_gender == 0 ? "female" : "male") << endl;
}
void getPerson(const vector<Person*>& persons, const int index, Person* searchPerson)
{
if (index < 0 || index >= persons.size()) {
cout << "index is invalid." << endl;
return;
}
searchPerson = persons[index];
searchPerson->printPersonInfo();
cout << searchPerson << endl;
cout << persons[index] << endl;
}
void doSomething(Person* person)
{
if (person == nullptr) {
cout << "Person not exist." << endl;
return;
}
person->printPersonInfo();
cout << person << endl;
}
int main()
{
vector<Person*> persons;
Person* person0 = new Person("Wang", 18, 0);
persons.emplace_back(person0);
Person* person1 = new Person("Zhao", 21, 1);
persons.emplace_back(person1);
Person* person2 = new Person("Qian", 24, 0);
persons.emplace_back(person2);
cout << persons.size() << endl;
Person* searchPerson = nullptr;
getPerson(persons, 0, searchPerson);
doSomething(searchPerson);
cout << searchPerson << endl;
for (int i = 0; i < persons.size(); ++i)
{
delete persons[i];
persons[i] = nullptr;
}
return 0;
}
在上面的例子中,新建了Person
类,流程如下:
- 构造一个
persons
指针数组 - 构造一个空的Person指针
searchPerson
- 在
getPerson
函数中查找匹配的指针并赋值给searchPerson
- 在
doSomething
中操作该指针,这里只是简单的个人信息打印printPersonInfo
上面的代码运行结果如下
call constructor.
call constructor.
call constructor.
3
name:Wang, age:18, gender:female
00000281A88A4FC0
00000281A88A4FC0
Person not exist.
0000000000000000
call deconstructor.
call deconstructor.
call deconstructor.
可以看到getPerson
函数中searchPerson
的地址是00000281A88A4FC0
但是在doSomething
函数中操作时却是空的,这实在很郁闷
问题分析
问题的根本还是对指针和函数的理解不够清晰
- 指针本身也就是4个字节的变量,只不过这个变量内部存储的是地址而已
- 函数按值传递,内部形参的改变不会影响外部的实参
弄清楚上面的两点,问题就比较明显了
在 getPerson
函数中,searchPerson
是按值传递的(指针按值传递),对它的修改不会影响调用者的值
void getPerson(const vector<Person*>& persons, const int index, Person* searchPerson)
searchPerson = persons[index];
的修改仅限于 getPerson
函数内部,调用者中的 searchPerson
仍然是 nullptr
将 searchPerson
改为按引用传递:
void getPerson(const vector<Person*>& persons, const int index, Person*& searchPerson)
这样 searchPerson
的值在函数内部修改后,会正确反映到调用者的上下文中
调整后的打印输出如下
call constructor.
call constructor.
call constructor.
3
name:Wang, age:18, gender:female
0000015F986F4FC0
0000015F986F4FC0
name:Wang, age:18, gender:female
0000015F986F4FC0
0000015F986F4FC0
call deconstructor.
call deconstructor.
call deconstructor.
可以看到searchPerson
已经非空,可以在doSomething
中正常操作
总结
指针引用是指引用一个指针,即一个指针变量本身作为引用的目标。这种技术允许修改指针本身(即让它指向其他地址)而不仅仅是修改它指向的内容。通过指针引用,可以在函数中直接改变调用者传入的指针的值
指针引用的主要用途包括:
- 修改指针的值(指向的地址):
在函数内部修改指针,使其指向不同的内存地址,并让这种修改在调用者中生效 - 避免多级指针的复杂性:
如果没有指针引用,修改指针值可能需要使用二级指针;使用指针引用可以简化代码逻辑