关于在C ++中重载[]
运算符,特别是其const
版本的另一个问题。
根据cppreference page on operator overloading,当重载数组下标运算符时
struct T { value_t& operator[](std::size_t idx) { return mVector[idx]; } const value_t& operator[](std::size_t idx) const { return mVector[idx]; } };
如果已知值类型是内置类型,则const变体应按值返回。
因此,如果value_t
可能是内置类型,则const
变体应该看起来
const value_t operator[](std::size_t idx) const { return mVector[idx]; }
甚至可能
value_t operator[](std::size_t idx) const { return mVector[idx]; }
因为const
限定符在这样的返回值上不是很有用。
现在,我有一个模板化的class T
(以保持与引用相同的命名),它与内置数据类型和用户定义的类型一起使用both,其中一些可能很重。
template<class VT>
struct T
{
VT& operator[](std::size_t idx) { return mVector[idx]; }
const VT& operator[](std::size_t idx) const { return mVector[idx]; }
};
根据以上给出的建议,我应该将enable_if
与某些type_traits
一起使用,以区分具有内置/非内置类型的模板化类实例化。
我必须这样做吗?此建议是否为[[only,以避免对内置类型进行潜在的不必要的取消引用,或者隐藏在其中应引起注意的其他内容?
注:
有关StackOverflow的现有问题:
type_traits
建议在没有明确理由的情况下使用“应该更好”的结构返回副本。此“应该更好”与C++ FAQ entry on basic rules and idioms for operator overloading中的“应该”稍有不同,这加深了我的困惑。const value_t&
。const value_t
变量返回value_t&
,为const
变量返回const value_t&
。如您的示例中所示,重载通常很短,因此无论如何,它们将在每个呼叫站点内联。在那种情况下,重载返回按值还是按引用都没有关系,无论哪种情况,间接寻址都将被优化。任何设置为至少较低的优化级别的现代编译器都应这样做。
[我没有其他理由可以不同地处理基本类型。
如果返回对元素的const
引用,则用户可以保留该引用并观察容器元素的变化(直到引用失效以某种指定的方式发生)。如果返回值,则无法观察到更改。
如果用户能够获得参考并观察某些类型的未来变化,而其他类型则无法观察,这将令用户感到惊讶。最坏的情况是,如果他们也使用类型通用代码,则还需要对所有模板进行条件处理。
此外,即使您返回基本类型的按值,也仅通过对对象的const
引用来调用返回按值的重载。在大多数情况下,用户可能具有您容器的非const
实例,并且要利用这种潜在的优化方法,他们需要在调用成员函数之前先将其对象引用显式转换为const
。
因此,如果需要优化,我宁愿添加一个附加成员函数,该成员函数
always]返回容器元素按值的副本,并且如果潜在的取消引用被确定为性能问题,则用户可以使用该副本。调用此成员函数不会比确保调用正确的运算符重载更麻烦。