为什么需要一个指针来初始化堆上的对象,而不是堆栈上的对象?

Tez*_*Tez 3 c++ heap stack pointers class

例如,在这两个代码中,一个不需要指针,另一个不需要.为什么是这样?如果myObject1不是指针,那究竟是什么?

class Object{
…
};


int main(){
    // Create instance on the stack
    Object myObject1;

    // Create instance on the heap
    Object *myObject2 = new Object;

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

谢谢你的帮助.

Jos*_*eld 7

这两个声明都是具有自动存储持续时间的对象的定义.也就是说,它们都会在函数结束时被销毁.第一个是声明一个Object类型对象,第二个是一个Object*类型对象.

只是初始化器myObject2是一个新表达式.新表达式动态分配对象并返回指向它的指针.myObject2正在使用指向动态分配的指针进行初始化Object.

因此,您正在目睹创建对象的两种不同方式.一个是变量定义,一个是new-expression.

任何其他方式都没有意义.想象一下,new-expression没有返回指向该对象的指针,而是直接引用该对象.然后你可能会这样写:

Object myObject2 = new Object();
Run Code Online (Sandbox Code Playgroud)

但是,默认情况下,C++使用值语义.这意味着动态分配的对象将被复制到myObject2,然后您已经丢失了它.您无法再获取该对象的地址.一个新的表达,让你有一个手柄来动态分配的对象返回一个指针.

你可能会说,"那就是我用Java写它的方式!" 但那是因为Java以不同的方式工作.在Java中,myObject2是您设置为指向新Object对象的引用.它不以任何方式复制对象.

在动态分配对象时,C++不要求必须使用指针.事实上,你可以做这样的事情(这是一种Java等价物):

Object& myObject2 = *(new Object());
Run Code Online (Sandbox Code Playgroud)

但这是一个非常糟糕的主意.它突然掩盖了这样一个事实,即对象是动态分配的,并且很容易犯错并忘记销毁对象(在Java中你不必关心它).至少一个指针可能会提醒你这样做.但是,即使这样也会导致错误或不清楚的代码,这就是为什么建议您尽可能使用智能指针.

简而言之:这就是新表达式的行为方式.它动态分配一个对象,然后返回一个指向它的指针.