例如,在这两个代码中,一个不需要指针,另一个不需要。为什么是这样?如果myObject1不是指针,那究竟是什么?
class Object{
…
};
int main(){
// Create instance on the stack
Object myObject1;
// Create instance on the heap
Object *myObject2 = new Object;
return 0;
}
感谢您的帮助。
答案 0 :(得分:7)
您的两个声明都是具有自动存储持续时间的对象的定义。也就是说,它们都会在函数结束时被销毁。第一个是声明Object
类型对象,第二个是Object*
类型对象。
myObject2
的初始化程序恰好是 new-expression 。新表达式动态分配对象并返回指向它的指针。正在使用指向动态分配的myObject2
。
Object
因此,您正在目睹创建对象的两种不同方式。一个是变量定义,一个是 new-expression 。
任何其他方式都没有意义。想象一下, new-expression 没有返回指向对象的指针,而是直接引用该对象。然后你可以这样写:
Object myObject2 = new Object();
但是,默认情况下,C ++使用值语义。这意味着动态分配的对象将被复制到myObject2
,然后您已经丢失了它。您无法再获取该对象的地址。 new-expression 返回一个指针,以便您拥有动态分配对象的句柄。
你可能会说,“那就是我用Java写它的方式!”但那是因为Java以不同的方式工作。在Java中,myObject2
是您设置为指向新Object
对象的引用。它不会以任何方式复制对象。
C ++不要求在动态分配对象时必须使用指针。事实上,你可以做这样的事情(这是Java的等价物):
Object& myObject2 = *(new Object());
但这是一个非常糟糕的主意。它突然掩盖了这样一个事实,即对象是动态分配的,并且很容易犯错并忘记销毁对象(在Java中你不必关心它)。至少一个指针可能会提醒你这样做。但是,即使这样也会导致错误或不清楚的代码,这就是为什么建议您尽可能使用智能指针。
简而言之:这就是 new-expression 的行为方式。它动态分配一个对象,然后返回一个指向它的指针。
答案 1 :(得分:4)
它是类的实例(或对象)。 myObject2
指向到类的实例。
你也可以指向堆栈上的变量:
int main()
{
Object myObject1;
Object* pointerToObjectOnStack = &myObject1;
}
指针可指向任何地方;堆栈,堆或全局变量(既不在堆栈上也不在堆上)。
答案 2 :(得分:1)
例如,在这两个代码中,一个不需要指针,另一个不需要指针 确实。这是为什么?
因为你以一种(无保证的)尝试以这种方式编写它们以匹配你在上面写的评论。
如果myObject1不是指针,那究竟是什么?
Object
。也就是说,Object
类型的对象。也就是说,Object
类的实例。
答案 3 :(得分:1)
myObject1
是在堆栈中分配的Object
。
Here您将找到有关内存的更准确信息。
用两个词来说:
new
或malloc()
)数据都在堆中分配。 答案 4 :(得分:1)
当你在堆栈上分配一个对象时,编译器会为你完成所有脏工作(分配/处理),因此你不需要一个指针来使用该对象。当您引用myObject1时,您正在引用Object
本身,您只需访问其字段,方法等。
请注意,您始终可以使用&
运算符获取指向堆栈变量的指针。
Object myObject1; // This is the live instance of Object
Object * pObject1 = &myObject1; // Here you can obtain a pointer
// to myObject1
myObject1.someField = 42; // Accessing myObject1's data
另一方面,在堆上分配对象需要您管理这些对象(使用new / delete,malloc / free等手动分配/取消分配它们),所以首先得到指向内存的指针,其中对象是找到并使用它,您必须使用*
运算符取消引用它。
Object * myObject1 = new Object(); // Here you construct the Object manually
// and get the pointer to place, where Object
// was allocated.
(*myObject1).someField = 42; // Accessing myObject1's data, notice the
// dereference (*)
myObject1->someField = 42; // The same, written more easily
答案 5 :(得分:0)
当函数与一些元数据一起被调用时,作为函数一部分的每个对象都被分配在堆栈上。当编译器编译函数时定义该元数据结构 - >这导致从函数中快速访问那些变量(相对位置不会改变)。当函数返回时,这个内存总是(自动)释放。
虽然堆在内存的不同部分设置,但可以或不能根据逻辑使用。
你有一个错误,通过将代码分成两行很容易显示:
class Object{
…
};
int main(){
// Create instance of Object on the stack
Object myObject1;
// Create instance of a pointer to Object on the stack
Object *myObject2;
// Create instance of Object on the Heap and assigned its address to the pointer.
myObject2 = new Object;
return 0;
}
答案 6 :(得分:-3)
如果在堆栈上分配变量,编译器会隐式为您生成指针。
即。 Object myObject1; myObject1.foo();
将编译为
Object* myObject1_implicit_ptr = new(alloca(sizeof(Object))) Object;
myObject1_implicit_ptr->foo();
(alloca
在堆栈上分配内存)
在Object myObject1;
中,myObject1
是对象实例所在的内存位置名称,即其地址的别名(相对于堆栈帧指针)。
我们可以用operator&
查询该地址并存储到指针(一个包含地址的变量)中:
Object myObject1; // myObject1 == stack-frame-pointer + 123
Object* myObject1_ptr = &myObject1;