为什么需要 `operator[]`,当 `operator double*` 看起来已经可以胜任工作了?

3

operator[] 看起来是多余的,因为 operator double* 似乎已经足够了。

以下是我的代码:

struct CStandardData
{
  inline operator double* () { return m_standardData; }
  //inline double& operator [] (size_t ix) { return m_standardData[ix]; }
  size_t  m_standardDataRefCnt{ 0 };
  double m_standardData[1];
} sd;

我在各种不同的情况下使用sd,包括double *a = sdsd[x] = 5.0sd[x] >= sd[y]等等,而且无论我是否已将operator []注释或定义,代码似乎都能正确运行。
在什么情况下需要使用operator []
我可能应该添加一些背景信息:
我在整个大量代码(>5000行)中使用了动态分配的内部数据double sd[]。然后,由于需要复制包含它的对象并将副本传递给用户(double sd[]具有>10000个元素,因此我不想多做副本),我需要向这个双精度数组添加分配引用计数。这是我设计的方案,可以在不必修改使用它的大量代码的情况下实现,但我不确定省略operator []是否会导致任何问题。

2
必要性?没有。总会有替代选择,例如您可以使用double at(size_t ix) const { return m_standardData[ix]; }。依赖隐式转换是个人偏好或团队指南的问题。我更喜欢显式而非隐式,但这在C++中绝非标准做法。 - Eljay
2个回答

8

什么情况下需要使用运算符 []?

当你想让你的对象充当容器而不是指针时。例如,下面的代码:

MyContainer cnt;
if( cnt ) // something

如果您定义了operator double *,则代码将会编译通过。但是,一般情况下我不希望容器编译这段代码,因为这没有任何意义。

4
operator double*()也允许像void* ptr = cnt;这样的操作,这意味着MyContainer对象可以传递给任何需要void*参数的函数。它还允许诸如cnt + 42之类的表达式。因此,operator double*()提供了比实际需要更多的功能。相比之下,operator []只允许确切需要的内容,不多也不少。 - Nikos C.

-1

sd[x] = 5.0没有上下文来让编译器在调用operator []之前应用CStandardData的隐式用户定义转换为double *。如果明确执行这样的转换,则不需要重载operator []static_cast<double *>(sd)[x]

此外,重载operator []似乎也是一个好主意,因为它将允许您验证传递的索引是否有效。


2
你确定它没有足够的上下文吗?我在使用clang和C++17时看到了一个将CStandardData隐式用户定义转换为double*的操作,用于sd[x] = 5.0;。如果我将其更改为explicit operator double* () { return m_standardData; },那么就会防止隐式转换,正如人们所期望的那样。另一种替代static_cast的方法是sd.operator double*()[x] = 5.0; - Eljay
1
表达式 sd[x]; 本身就有足够的上下文来调用隐式用户定义的转换运算符,不是吗? - wally
1
@Eljay,编译器没有要求考虑可能的用户定义转换,如果应用,则会使后续操作或函数调用有效。也就是说,sd[x] 表示在 sd 对象上调用 operator [],就像 sd.foo() 表示在 sd 对象上调用函数 foo 一样。对我来说,这似乎是一件好事,因为 C++ 中的查找规则已经相当混乱了。 - user7860670
我不会逐字逐句地引用关于运算符重载解析以及内置候选项行为的章节。你可以自己查阅资料,而不是胡乱猜测。 - T.C.
@T.C. 这里甚至不考虑内置的候选项。 - user7860670
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接