为何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
背后的设计原因
标准迭代的时间差:std::array在C11就已加入标准库,而基于值类别区分成员函数重载的设计范式,是在C17引入
std::optional这类新组件时才被广泛应用的。早期标准库设计时,右值引用的最佳实践还未完全成熟。兼容性优先:标准委员会对已有标准库组件的修改极为谨慎,避免破坏现有代码的兼容性。虽然给std::array添加值类别重载逻辑上合理,但可能存在依赖当前行为的旧代码,因此没有贸然修改。
定位与权衡:std::array的核心定位是“轻量包装原生数组”,早期设计更侧重与原生数组在内存布局、性能特性上的对齐,而值类别匹配的语义完善被放在了次要位置。后续新增的标准库组件则吸收了更成熟的右值引用设计经验,自然支持了这类重载。
如果需要让右值std::array的访问返回右值引用,可以手动显式转换,比如对右值std::array的元素取右值引用:static_cast<T&&>(std::move(new_way)[pos])。
内容的提问来源于stack exchange,提问作者geza
相关产品推荐
相关产品推荐

