现代c++ 中定义方法参数的时候,什么时候传递指针,什么时候使用引用,什么时候使用值?

先说结论:想共享用引用,想可空/重指向用指针,想孤立副本用值。


1. 值传递 (T)

场景

  • 函数内部需要一份独立副本(修改不影响调用者)
  • 或者类型足够小intdoublechar、小型 POD),拷贝成本 ≈ 0

示例

int add(int a, int b);              // 原生类型
double norm(Vector3 v);             // Vector3 仅 3 个 double,64 字节以内可接受

注意
C++17 后对于"大对象"编译器会强制复制省略(RVO),但语义上仍是"我拿到了副本"。


2. const 引用 (const T&)

场景

  • 只读大对象(std::string、容器、复杂类),避免深拷贝
  • 调用者保证对象存在,且不为空
  • 不需要中途换指向

示例

bool login(const std::string& user, const std::string& pwd);
size_t countLines(const std::vector<int>& data);

3. 非 const 引用 (T&)

场景

  • 函数必须把结果写回调用者(输出参数)
  • 调用者保证对象存在,且不为空
  • 语义就是"我替你改"

示例

void split(const std::string& src, std::vector<std::string>& out);
void normalize(Vector3& v);         // 原地修改

4. 裸指针 (T*)

满足以下任一即可选指针:

  • 对象可能不存在 → 用 nullptr 表示
  • 需要中途重指向另一对象
  • 与 C 接口或旧库交互,它们只认指针
  • 动态多态,需要基类指针

示例

void draw(Shape* p);                // 可能为空,也可能指向子类对象
void freeResource(Resource* r);     // if (r) delete r;

提示
现代 C++ 优先用智能指针管理生命周期,裸指针只扮演"可选观察"或"非拥有"角色。


5. 智能指针

类型 语义 示例场景
unique_ptr<T> 独占所有权 工厂函数把对象交给调用者
shared_ptr<T> 共享所有权 需要延长生命周期的观察者
weak_ptr<T> 非拥有观察 打破 shared_ptr 循环引用

示例

std::unique_ptr<FILE, decltype(&fclose)>
takeOwnership(const char* path);    // 转移所有权

void observe(std::shared_ptr<Config> cfg);  // 只观察,生命期由别人托管

6. 一张速查表

形参形式 可空 可重指向 拷贝成本 推荐场景
T 高* 小对象或需要独立副本
const T& 极低 只读大对象
T& 极低 输出参数,调用者保证存在
T* 极低 可空、重指向、多态、C 接口
smart_ptr<T> 共享/转移所有权

*"高"是相对于引用而言;对可移动的大对象,C++17 后实际常常零成本。


7. 三句口诀选型

写函数签名前,按顺序问自己:

  1. 我要空吗?
  2. 我要换指向吗?
  3. 我要拷贝吗?
posted @ 2025-11-11 11:01  Tlink  阅读(25)  评论(0)    收藏  举报