C++如何在函数内让指针指向另一个指针?是否必须拷贝?
问题解答:让函数修改外部指针的指向
咱先直接给结论:完全可以实现让test()执行后,main里的b指向a的对象,根本不需要创建对象拷贝!你的代码没生效,是因为踩了C++「值传递」的常见坑——指针本身也是按值传递的,你传给test的b是个副本,函数里修改的只是这个副本的指向,完全影响不到main里原有的b指针。
原代码问题拆解
先把你的示例代码补全并格式化,方便看清楚:
#include <iostream> using namespace std; class Object {}; // 原代码未定义该类,补充完整 void test(Object* a, Object* b) { std::cout << "test a: " << a << std::endl; std::cout << "test b: " << b << std::endl; b = a; // 此处修改的是函数内部的b副本,与main中的b无关 std::cout << "test b assigned: " << b << std::endl; } int main() { Object* a = new Object(); Object* b = nullptr; test(a, b); std::cout << "a: " << a << std::endl; std::cout << "b: " << b << std::endl; // 因此这里b仍为nullptr delete a; delete b; // 此处delete nullptr虽无错误,但无实际意义 }
输出和你给出的一致:
test a: 0x1aa8930 test b: 0 test b assigned: 0x1aa8930 a: 0x1aa8930 b: 0
简单来说,test里的b是main中b的“替身”,你修改替身的指向,真身完全不会有变化。
三种可行的解决办法
1. 传递指针的指针(Object**)
要修改外部指针本身,就得把指针的地址传进去——相当于告诉函数“我的指针在这,你直接改它”:
void test(Object* a, Object** b) { std::cout << "test a: " << a << std::endl; std::cout << "test b的地址: " << b << std::endl; std::cout << "test 原b的当前值: " << *b << std::endl; *b = a; // 通过地址直接修改原指针的指向 std::cout << "test 修改后的原b值: " << *b << std::endl; } int main() { Object* a = new Object(); Object* b = nullptr; test(a, &b); // 用&取b的地址传递给函数 std::cout << "a: " << a << std::endl; std::cout << "b: " << b << std::endl; // 此时b与a指向同一对象 delete a; // 注意!此处不可再delete b,a和b指向同一块内存,重复释放会导致未定义行为 }
2. 传递指针的引用(Object*&)
C++的引用是原变量的“别名”,传递指针的引用后,函数里对引用的修改会直接作用于原指针,写法比指针的指针更简洁:
void test(Object* a, Object*& b) { // 这里b是指针的引用 std::cout << "test a: " << a << std::endl; std::cout << "test b: " << b << std::endl; b = a; // 直接修改原指针的指向,无需操作地址 std::cout << "test b assigned: " << b << std::endl; } int main() { Object* a = new Object(); Object* b = nullptr; test(a, b); // 直接传b即可,引用会自动绑定原变量 std::cout << "a: " << a << std::endl; std::cout << "b: " << b << std::endl; delete a; // 同样不可重复delete b }
这是C++中更推荐的写法,代码更干净,逻辑也更清晰。
3. 让函数返回指针
如果逻辑简单,也可以让test直接返回目标地址,再在main中赋值给b:
Object* test(Object* a) { std::cout << "test a: " << a << std::endl; return a; // 返回a的地址 } int main() { Object* a = new Object(); Object* b = nullptr; b = test(a); // 将返回值直接赋值给b std::cout << "a: " << a << std::endl; std::cout << "b: " << b << std::endl; delete a; }
这个方案最直观,适合不需要在函数内执行复杂操作的场景。
额外提醒
- 当
a和b指向同一对象时,绝对不能重复调用delete,这会导致内存重复释放,触发程序崩溃等未定义行为。 - 如果你的场景需要多个指针共享对象所有权,建议使用C++智能指针(如
std::shared_ptr),它能自动管理内存,避免手动delete的麻烦,也能规避这类问题。
内容的提问来源于stack exchange,提问作者user3364552
相关产品推荐
相关产品推荐

