对象创建差异
Object creation differences
以下两种创建对象的方法有什么区别?
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;
}
- 使用基类指针创建对象时,缺少派生类析构函数
- 如何创建对象函数指针C++映射?
- C++创建对象数组
- 在 C++ 的 Switch Case 中创建对象后对对象调用方法
- 如何获取在 main() 函数中构造的类的创建对象?
- 基于文件中的条目创建对象
- 错误:创建对象后无法分配区域
- C++ 通过输入创建对象
- 堆还是堆栈用于创建对象?
- 使用 C++ 创建对象数组
- 使用unique_ptr创建对象
- C++递归地在类构造函数中创建对象
- 通过向构造函数其他对象引用页面来创建对象
- ReactiveX (rx) - 在对象上应用可观察对象,而不是在可观察对象中创建对象
- 如何在OSX上正确创建C++对象文件(.o)
- 编译器是否会创建vtable,而不考虑在c++中创建对象
- 创建对象并防止被破坏
- 在C++中,友元类可以从友元类创建对象吗
- 只在堆中创建C++对象
- 创建用户定义的复制构造函数时无法创建对象