( - >)箭头操作符和(。)点操作符,类指针

时间:2013-07-18 06:39:52

标签: c++ class pointers

在c ++中,我们知道对于类的指针,我们使用( - >)箭头操作符来访问该类的成员,如下所示:

#include <iostream>
using namespace std;

class myclass{
    private:
        int a,b;
    public:
        void setdata(int i,int j){
            a=i;
            b=j;
        }
};

int main() {
    myclass *p;
    p = new myclass;
    p->setdata(5,6);
    return 0;
}

然后我创建了一个“myclass”数组。

p=new myclass[10];

但是,当我通过( - &gt;)箭头操作符访问myclass成员时,出现以下错误

base operand of '->' has non-pointer type 'myclass'

但是当我通过(。)运算符访问类成员时它可以工作。这些事让我感到困惑。为什么类I的数组必须使用(。)运算符。

6 个答案:

答案 0 :(得分:15)

您应该阅读有助于您了解问题的pointers and reference之间的区别。

简而言之,不同之处在于:
当您声明myclass *p时它是一个指针,您可以使用->访问其成员,因为p指向内存位置。

但是,只要您致电p=new myclass[10]; p开始指向数组,并且当您致电p[n]时,您会获得一个引用,必须使用.来访问哪些成员。
但是,如果您使用的p->member = smth与调用p[0].member = smth的情况相同,那么[]中的数字是从p到搜索下一个数组成员的偏移量,例如(p + 5)->member = smthp[5].member = smth

相同

答案 1 :(得分:7)

请注意,对于指针变量x

myclass *x;
  • *x表示“获取x指向的对象”
  • x->setdata(1, 2)(*x).setdata(1, 2)相同,最后
  • x[n]表示“获取数组中的第n个对象”。

因此,例如x->setdata(1, 2)x[0].setdata(1, 2)相同。

答案 2 :(得分:4)

因为使用[]像p [3],你已经取消引用了指向数组+索引移位的指针。之后你必须使用“。”,因为p [3]是一个对象,而不是一个指针。

答案 3 :(得分:3)

在...

MyClass* p = new myclass[10];

... p是指向MyClass对象数组的指针。 “指向数组的指针”必须首先进行删除。只要有指向数组的指针,p[n]就会有效地为数组中的第n个元素提供引用,因此您实际上拥有MyClass&那是为什么.需要访问MyClass成员ala p[n].member,以及为什么在这种情况下指针特定的->符号是错误的。 ...

请注意p->member(对于任何成员)仍然有效且等效于p[0].member,因此您只能使用它来访问数组中的第一个元素。我强烈建议你不要在编程上下文中使用它,其中'p'已知是指向数组的指针,因为它隐藏了p是一个数组的事实。有时虽然你可以创建另一个指针 - 比如q - 目的是引用单个数组元素 - 可能是也可能不是[0] - 在这种情况下使用q->member是公平的。像q这样的变量也可用于对数组进行迭代。但是,有时你需要delete[] p; - 所以你不会在事先改变p之前......你不想忘记p[0]地址或delete[] p;将是未定义的行为(如果p仍然指向数组中,则允许实现定义并恰好在Windows上,但不会是可移植的。)

答案 4 :(得分:2)

myclass *ptr;

ptr = new myclass();     // ptr points to a single object
ptr->doSomething();      // calls doSomething on the object _pointed to_

ptr = new myclass[10];   // ptr points to multiple objects
ptr->doSomething();      // calls doSomething on the first object _pointed to_
(ptr+1)->doSomething();  // calls doSomething on the second object _pointed to_

auto val = ptr[2];       // fetches a reference to the second _object_ to val.
val.doSomething();       // calls doSomething on the _object reference_ val.

换句话说,当索引数组以获取第n个元素时,你没有将指针提取到第n个元素,而是获取对实际对象的引用,需要使用.语法访问其成员。

答案 5 :(得分:1)

考虑到

,也许考虑到这一点很有见地
myclass obj;
auto p = &obj;  // avoid `new` with plain pointers. That combination is
               //  safer replaced by unique_ptr or std::vector.

以下将全部有效并且是等效的:

p->setdata(5, 6);
(*p).setdata(5, 6);
p[0].setdata(5, 6);
0[p].setdata(5, 6);

显示[]实际上是一个指针解除引用运算符,只需要额外的功能就可以将偏移量添加到普通的C数组中。

在C ++代码中使用C数组通常是个问题;您示例的明显替代方法是std::vector

std::vector<myclass> array(10);

此处,array[n]可以像之前的p[n]一样使用,但

  • 你没有得到任何愚蠢的指针 - 想法,因为界面中没有指针
  • 您可以获得正确的自动内存管理,即当阵列超出范围时,它会自动删除对象及其内存
  • 如果需要(array.at(n)
  • ,您可以进行边界检查
  • 您可以使用(C ++ 11)for(auto& obj: array){...}
  • 轻松遍历整个数组