You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C++中引用函数是否仍需取地址运算符&?标准依据及C++23变化

关于C++函数名传参是否需要加&的疑问解答

核心结论

在C++中,传递函数名时是否加&取地址运算符完全是可选的——两种写法std::thread t(foo);和std::thread t(&foo);在标准下是合法且行为等价的,加&不是语法要求,只是风格选择。


1. 函数名的隐式转换(标准规定)

根据C++标准的**[expr.prim.id.unqual]**条款:当函数名出现在需要作为表达式使用的语境中(除非是sizeof、decltype等不需要转换的运算符操作数),会自动隐式转换为指向该函数的指针。

举个简单例子:

void foo() {}

// 以下两行完全等价,foo会自动转换成&foo
void (*fp1)() = foo;
void (*fp2)() = &foo;

cppreference提到的“函数不是对象,无法按值传递或返回”是准确的——你确实不能直接传递函数本身,但传递函数名时,编译器会自动生成对应的函数指针,实际传递的是这个指针,而非函数本体,这完全符合标准规则。


2. std::thread构造函数的处理逻辑(C++20及更早)

在C++20及之前,std::thread的模板构造函数会通过decay-copy处理传入的可调用对象。对于函数名来说,decay操作会把函数类型直接转换成对应的函数指针类型。所以不管你传foo还是&foo,经过decay-copy后得到的都是同一个函数指针,最终的线程行为没有任何区别。


3. C++23的构造函数变化不影响此场景

C++23将std::thread构造函数的处理逻辑改为使用auto std::forward(f),但这并不会破坏原有行为:

  • 当你传入函数名foo时,它作为左值会依然触发隐式转换,生成函数指针;
  • 传入&foo时,本身就是函数指针,std::forward会直接传递这个指针。

两种写法在C++23中依然等价,不会出现行为差异,你完全不用担心兼容性问题。


4. 为什么有人习惯加&?

这纯粹是编码风格问题:

  • 加&可以更直观地表明这里传递的是函数指针,让代码意图更清晰,减少新手的困惑;
  • 某些场景下(比如传递重载函数时),加&可以帮助编译器明确选择哪个重载版本,但对于无重载的普通函数来说,这不是必须的。

内容的提问来源于stack exchange,提问作者Superlokkus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 19:58:14