【问题标题】:Why won't [ ] brackets work when dereferencing a pointer?为什么在取消引用指针时 [ ] 括号不起作用?
【发布时间】:2017-06-07 09:07:21
【问题描述】:

如果我有一个 std::vector,我可以访问一个成员,因为方括号运算符在矢量类中被重载。如果我有一个指向向量的指针,我可以取消引用指针并使用这个运算符。但是使用箭头 -> 运算符它不会让我使用它。示例:

 // Excuse the UB here, it's just for illustration
    std::vector<int> myVector;    
    std::vector<int>* pToVector;
    myVector[4] = 0;                   // Works fine
    (*pToVector)[4] = 0;               // Works fine
    pToVector->[4] = 0;                // Doesn't work
    (pToVector->)[4] = 0;              // Doesn't work

看起来好像 -> 箭头运算符取消了指针的引用,是否有理由不期望这会起作用?或者它只是语言的其中之一?

谢谢。

【问题讨论】:

  • 前 2 个分配可能看起来有效,但您正在访问容器边界之外,即 UB。您需要像这样声明它std::vector&lt;int&gt; myVector(5) 它将分配必要的空间来访问myVector[4] 后两者是非法构造
  • 语法不正确。箭头运算符为您提供 *objec。结构所以 pToVector->[4] = 0 类似于 *pToVector.[4] = 0. 这条线(pToVector->)[4] 和这条pToVector->[4] 都不起作用
  • 您为什么希望它起作用? a-&gt;b 表示 (*a).b。所以,a-&gt;[b] 可能意味着 (*a).[],这没有任何意义。
  • -&gt;[4] 根本不符合语法。这!就像:sENTECE?
  • 请注意,myVector.[4] 也不起作用。

标签: c++ arrays pointers vector dereference


【解决方案1】:
std::vector<int> myVector;    
std::vector<int>* pToVector;
myVector[4] = 0;                   // Works fine.
(*pToVector)[4] = 0;               // Works fine
pToVector->[4] = 0;                // Doesn't work
(pToVector->)[4] = 0;              // Doesn't work

如果必须使用指向对象的指针来访问对象类的重载运算符,则必须显式调用它。

pToVector->operator[](4)

...顺便说一句,访问myVector.size() 之外的索引是未定义的行为。这包括代码中关于// Works fine 的带有注释注释的语句。

【讨论】:

    【解决方案2】:

    后两行的正确语法是:

    (*pToVector)[4] = 0; 
    //dereference the pointer and then call operator[] on the object returned by the dereference
    

    您可以使用-&gt; 运算符来访问常规成员函数,如下所示:

    pToVector->size();
    

    从技术上讲,您可以尝试按名称调用operator[],但它更冗长。

    【讨论】:

      【解决方案3】:

      原因是[]是一个操作符,短操作符语法不需要也不允许成员访问操作符。这适用于成员访问运算符.-&gt;,这是有道理的,因为后者只是(*a).b 的简写。

      例如全部禁止a. &amp; ba-&gt;^b

      从技术上讲,它也适用于罕见的.*-&gt;*。请注意,后者不是-&gt;后跟operator*,而是指向成员指针解引用的指针。

      【讨论】:

        【解决方案4】:

        -&gt; 运算符是点运算符的替代品,除了它首先取消引用一个指针。它用于访问属性(成员和函数)。对于您的操作,operator[] 是属性。所以,pToVector-&gt;operator[](4) 应用于(*pToVector)[4] = 0

        【讨论】:

        • -&gt; 不限于数据成员,它也适用于成员函数。显然operator[ ] 是一个函数成员,而不是数据。
        • attribute这个词比较合适。但我说数据字段@MSalters 时可能指成员和方法
        • attribute 不是关键字,attributes 是完全不同的东西。此外,“成员和方法”没有什么意义;方法是成员的子集。 (即成员函数)。
        • 我的意思是“单词”。我想知道为什么像你这样的老人对这些东西很着迷。 @MSalters。顺便说一句,a nod is as good as a wink to a blind horse
        • 如果您认为我们很着迷,请与编译器作者见面。我们是一致的,因为这些词有特定的含义,不同的词有不同的含义。例如,因为main 不是关键字,您可以拥有一个名为main 的数据成员。
        【解决方案5】:

        -&gt; 运算符不只是取消引用,它还访问一个成员。您正在访问元素*,而不是成员。 -&gt; 本来可以定义为允许这样做,但没有。

        * 更准确地说,向量让您可以像访问数组元素一样访问对象,但不会改变语法。

        【讨论】:

        • “元素”与“成员”? C++ 没有这样的区别;这些术语可以互换使用。
        • @MSalters 您是否有 C++ 标准引用类元素或数组成员的示例?我没有找到它们,但我可能忽略了某些东西。
        • @hvd:我读到你的陈述有点误导,因为“-&gt; 正在访问一个元素”,但没关系。 C++ 没有正式定义 element 并且标准中只有 element_type 在索引中,但 1.8/2 几乎没有疑问。也就是说,在这个问题中[ ] 不访问数组元素,而是引用成员函数operator[ ]。相同的标记,不同的含义。
        • @MSalters 公平点,重载的operator[] 意味着它只是一个假装有元素的类。将编辑,谢谢。
        • 我喜欢听听他们的经历。尽管如此,我受够了这里的灯光师的痴迷@hvd
        【解决方案6】:

        我认为方括号取消引用指针,所以你最终在那里取消引用了两次。

        ptoVector[4] 我认为会起作用并且足够了,因为方括号为您取消引用。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-05-09
          • 2011-02-24
          • 2016-08-09
          • 2013-04-01
          • 2014-05-09
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多