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

为何std::array的operator[]不保留数组的值类别?

为什么std::array的访问函数不区分值类别提供重载?

我原本以为当std::array是右值时,调用operator[]会返回右值,但实际并非如此——它没有按值类别区分的重载。反观std::optional,就会尊重值类别提供对应的重载,比如:

const T &&operator[](size_type pos) const &&
const T &operator[](size_type pos) const &
T &&operator[](size_type pos) &&
T &operator[](size_type pos) &

这个问题不止出现在operator[]上,std::array的所有访问函数都存在这个情况。

下面的代码可以直观展示std::array和原生数组的差异:原生数组作为右值时,下标运算符会返回右值引用,但std::array做不到这一点:

#include <array>
#include <utility>
#include <type_traits>
#include <cstdio>

int main() {
    int old_way[1];
    std::array<int, 1> new_way;

    printf("old_way, is_rvalue_reference: %d\n", std::is_rvalue_reference_v<decltype(std::move(old_way)[0])>);
    printf("new_way, is_rvalue_reference: %d\n", std::is_rvalue_reference_v<decltype(std::move(new_way)[0])>);
}

程序输出:

old_way, is_rvalue_reference: 1
new_way, is_rvalue_reference: 0

背后的设计原因

  1. 标准迭代的时间差:std::array在C11就已加入标准库,而基于值类别区分成员函数重载的设计范式,是在C17引入std::optional这类新组件时才被广泛应用的。早期标准库设计时,右值引用的最佳实践还未完全成熟。

  2. 兼容性优先:标准委员会对已有标准库组件的修改极为谨慎,避免破坏现有代码的兼容性。虽然给std::array添加值类别重载逻辑上合理,但可能存在依赖当前行为的旧代码,因此没有贸然修改。

  3. 定位与权衡:std::array的核心定位是“轻量包装原生数组”,早期设计更侧重与原生数组在内存布局、性能特性上的对齐,而值类别匹配的语义完善被放在了次要位置。后续新增的标准库组件则吸收了更成熟的右值引用设计经验,自然支持了这类重载。

如果需要让右值std::array的访问返回右值引用,可以手动显式转换,比如对右值std::array的元素取右值引用:static_cast<T&&>(std::move(new_way)[pos])。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 18:32:01