c++中void func(int arr[])实际传指针而非引用,因数组参数自动退化为int*;正确做法是用模板推导长度并声明引用类型int (&arr)[n],或c++20的std::span实现类型安全与长度检查。

为什么不能直接用 void func(int arr[]) 传数组引用
这种写法实际上传的是指针,不是引用。C++ 中 int arr[] 在函数参数里会自动退化为 int*,丢失长度信息,也无法阻止数组被隐式转换——你根本没法在函数内用 sizeof(arr) 得到真实大小,decltype(arr) 也是指针类型。
- 即使你声明
void func(int arr[5]),编译器照样当int*处理 - 无法绑定到临时数组,也不能防止调用时传入长度不符的数组
- 想靠它实现“只接受 5 元素数组”的约束?做不到
正确写法:用模板推导数组长度 + 引用声明
必须显式写出数组长度和引用符号 &,且长度得是编译期常量。最稳妥的方式是用模板让编译器自己推:
template <size_t n>
void process_array(int (&arr)[N]) {
// 这里 arr 是真正的 int[5]& 类型
std::cout <ul>
<li>调用时 <code>int a[5] = {1,2,3,4,5}; process_array(a);</code> 才能成功匹配</li>
<li>如果传 <code>int b[3]</code>,会实例化出另一个 <code>process_array</code> 版本</li>
<li>传 <code>std::vector<int></int></code> 或 <code>new int[5]</code> 直接编译失败——这正是你想要的安全性</li>
</ul>
<h3>如果必须支持不同长度,用 <code>std::span</code>(C++20)</h3>
<p>模板方案虽然安全,但每次长度不同就生成新函数,代码膨胀。C++20 的 <code>std::span</code> 提供运行期长度 + 编译期类型安全:</p><div class="aritcle_card flexRow artxards">
<div class="artcardd flexRow">
<a class="aritcle_card_img" rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master"><img
src="https://img.php.cn/upload/skill/000/000/081/179051228971575.jpg" alt="C++ Code Review Master" onerror="this.onerror='';this.src='/static/lhimages/moren/morentu.png'" ></a>
<div class="aritcle_card_info flexColumn">
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="overflowclass">C++ Code Review Master</a>
<p class="overflowclass">组合式C++代码评审方案,融合静态分析、AI推理、多轮迭代评审和C++专项检查,适用于PR审查、增量代码审查、全项目评审和代码质量评分,触发词包括review cpp、cpp代码评审、C++review、代码审查。</p>
</div>
<a rel="nofollow" href="/xiazai/skill5502" title="C++ Code Review Master" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span>
</a>
</div>
</div>
<pre class="brush:php;toolbar:false;">#include <span>
void handle_span(std::span<const int> s) {
for (int x : s) { /* ... */ }
std::cout <ul>
<li>可接受 <code>int arr[10]</code>、<code>std::vector<int></int></code>、<code>std::array<int></int></code>
</li>
<li>底层仍是轻量级指针+长度,无拷贝开销</li>
<li>注意:MSVC 19.29+、GCC 10+、Clang 9+ 才完整支持;老编译器可用 <code>gsl::span</code> 替代</li>
</ul>
<h3>常见错误:把 <code>int& arr[]</code> 当成“数组引用”</h3>
<p>这个语法合法,但含义是“元素为 <code>int&</code> 的数组”,即 <code>int&[5]</code>,不是“对整个数组的引用”。它要求你传入 5 个独立的 <code>int&</code>,比如:</p>
<pre class="brush:php;toolbar:false;">int a=1,b=2,c=3,d=4,e=5;
func({a,b,c,d,e}); // OK —— 传 5 个引用
- 你无法用一个数组变量(如
int x[5])直接初始化它 - 几乎没人这么用,容易和
int (&arr)[5]混淆,建议彻底避开 - 真要引用多个变量,用
std::tie或结构体更清晰
数组引用的核心就两点:长度必须已知,引用符号 & 必须紧贴括号。漏掉任一,就不是你想要的“整个数组按引用传递”。
C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!










