我来自Java背景,已经开始使用C++中的对象。但我想到的一件事是,人们经常使用指向对象的指针,而不是对象本身,例如这样的声明:

Object *myObject = new Object;

而不是:

Object myObject;

或者不用函数,让我们说testFunc(),如下所示:

myObject.testFunc();

我们必须写下:

myObject->testFunc();

但我不明白我们为什么要这样做。我认为这与效率和速度有关,因为我们可以直接访问内存地址。我说得对吗?


当前回答

C++中对象指针的关键优势是允许同一超类的指针的多态数组和映射。例如,它允许将长尾鹦鹉、鸡、知更鸟、鸵鸟等放在鸟的阵列中。

此外,动态分配的对象更灵活,可以使用HEAP内存,而本地分配的对象将使用STACK内存,除非它是静态的。堆栈上有大型对象,尤其是使用递归时,无疑会导致堆栈溢出。

其他回答

在内存利用率很高的领域,指针很方便。例如,考虑一个极大极小算法,其中将使用递归例程生成数千个节点,然后使用它们来评估游戏中的下一个最佳移动,解除分配或重置(如智能指针)的能力显著减少了内存消耗。而非指针变量继续占用空间,直到其递归调用返回值。

使用指向对象的指针有很多好处-

效率(正如你已经指出的)。将对象传递到函数意味着创建对象的新副本。使用第三方库中的对象。如果您的对象属于第三方代码,作者打算仅通过指针(无复制构造函数等)使用其对象,这是唯一可以绕过此问题的方法对象正在使用指针。传递值可能会导致问题。(深拷贝/浅拷贝问题)。如果对象拥有资源,并且您希望该所有权不应与其他对象共享。

指针有很多用例。

多态行为。对于多态类型,指针(或引用)用于避免切片:

class Base { ... };
class Derived : public Base { ... };

void fun(Base b) { ... }
void gun(Base* b) { ... }
void hun(Base& b) { ... }

Derived d;
fun(d);    // oops, all Derived parts silently "sliced" off
gun(&d);   // OK, a Derived object IS-A Base object
hun(d);    // also OK, reference also doesn't slice

引用语义和避免复制。对于非多态类型,指针(或引用)将避免复制可能昂贵的对象

Base b;
fun(b);  // copies b, potentially expensive 
gun(&b); // takes a pointer to b, no copying
hun(b);  // regular syntax, behaves as a pointer

注意,C++11具有移动语义,可以避免将昂贵的对象复制到函数参数中并作为返回值。但是使用一个指针肯定会避免这些问题,并且允许在同一个对象上使用多个指针(而一个对象只能从一次移动)。

资源获取。在现代C++中,使用新运算符创建指向资源的指针是一种反模式。使用特殊的资源类(标准容器之一)或智能指针(std::unique_ptr<>或std::shared_ptr<>)。考虑:

{
    auto b = new Base;
    ...       // oops, if an exception is thrown, destructor not called!
    delete b;
}

vs.

{
    auto b = std::make_unique<Base>();
    ...       // OK, now exception safe
}

原始指针只能用作“视图”,而不能以任何方式涉及所有权,无论是通过直接创建还是通过返回值隐式创建。另请参阅C++常见问题解答中的问答。

更细粒度的生命周期控制每次复制共享指针(例如作为函数参数)时,它指向的资源都保持活动状态。常规对象(不是由new创建的,直接由您创建或在资源类中创建)在超出范围时被销毁。

我将包括指针的一个重要用例。当您在基类中存储一些对象时,但它可能是多态的。

Class Base1 {
};

Class Derived1 : public Base1 {
};


Class Base2 {
  Base *bObj;
  virtual void createMemerObects() = 0;
};

Class Derived2 {
  virtual void createMemerObects() {
    bObj = new Derived1();
  }
};

因此,在这种情况下,不能将bObj声明为直接对象,必须有指针。

“需要是发明之母。”我想指出的最重要的区别是我自己编码经验的结果。有时需要将对象传递给函数。在这种情况下,如果您的对象是一个非常大的类,那么将其作为对象传递将复制其状态(您可能不希望..AND可以是big OVERHEAD),从而导致复制对象的开销。而指针是固定的4字节大小(假设为32位)。上面已经提到了其他原因。。。