对象创建差异

Object creation differences

本文关键字:创建 对象      更新时间:2023-10-16

以下两种创建对象的方法有什么区别?

Test* t = new Test();

Test* t;

你对第二个样本的回答与我认为的一致(没有创建对象),但

class Test {
        public:
                void bla(void) {
                        std::cout << "test" << std::endl;
                };
};
int main(void) {
        Test* test;
        test->bla();
}

给我输出"测试"。。。所以实际上有一个对象

第一个做4件事:

  • 创建指向Test的指针
  • 分配内存并创建Test对象(注意,它是Test,而不是test
  • 新对象是值初始化的,因为()-请参阅类型名称后的括号与new有区别吗?了解更多信息
  • 初始化指针以指向创建的对象

第二个只是创建指向Test的指针。而且它没有初始化。


@瑜伽士-对于您的编辑-这完全是未定义的行为,因为指针未初始化。不,它不是对象。有关详细信息,请参阅在未初始化对象的情况下调用的C++函数。

第二个根本不创建任何对象,试图访问它会导致糟糕的事情™.

这是一个指针,在堆栈上分配,使用32或64位内存。

Test * t;

这将在堆上创建一个Test类型的对象(需要对其进行脱盐)

t = new Test();

这将在堆栈上创建一个Test类型的对象(无需对其进行脱盐。一旦退出当前上下文,它就会消失)

Test t2;

编辑

您的示例之所以有效,是因为编译器对您的代码进行了优化:它注意到您没有使用任何成员,因此它可能不会像您查找实例那样努力。

第一个是创建对象实例的方法。

上的第二个不是创建对象实例的方法。它只是声明了一个指针,这个指针仍然是未初始化的。

更新后:它仍然成功调用bla()的原因只是未定义的行为。因为这正是C++标准定义的,当你使用不安全的内存(在这种情况下,你的指针指向某个任意地址)时会发生什么——行为是未定义的。

正如其他人已经说过的,你很幸运,你触发的未定义行为恰好看起来像你想要的(本质上是因为你的Test::bla()几乎像一个全局自由函数)。要查看您的示例崩溃和烧录,只需添加一些不重要的类成员:

class Test {
public:
  void bla(void) {
    std::cout << "test: " << x << std::endl;
  };
  int x;
};

你可以把你原来的例子想象成一个免费的

void bla(Test * p) { std::cout << "test" << std::endl; }

您只是碰巧用一个垃圾参数调用了它,但由于您没有使用该参数,所以不会发生任何错误。在我修改后的示例中,我们尝试访问p->x并死亡。

 Test* test;         
 test->bla(); 

正如其他答案所述,Test* test不创建任何对象。它是指向Test的未初始化指针。除非初始化为指向有效的Test对象,否则它不会指向任何有效的对象。

像您这样取消引用未初始化的指针会导致未定义的行为
在您的情况下,它不会崩溃,因为您没有在bla()中引用this
然而,它对test去引用的行为仍不明确。

为了重申以上观点,下面的示例将大部分崩溃。

#include<iostream>
class Test 
{
    public:
        int i; 
        void bla(void) 
        {
            std::cout << "test" << std::endl;
            std::cout << "test->i" << this->i <<std::endl;
        }
};
int main(void) 
{
    Test* test;
    test->bla();
    return 0;
}