我正在通过阅读教科书来学习C ++。 “对象和指针”部分说,声明指向这样的对象的指针:
SomeClass *ptrMyClass;
本身没有任何作用。只有在定义了Class的实例之后才有意义,如下所示:
SomeClass *ptrMyClass;
ptrMyClass = new SomeClass;
或者将它们组合在一起:
SomeClass *ptrMyClass = new SomeClass;
我的问题是,为什么我们必须使用'new'在堆上创建SomeClass的实例?到目前为止,在本书中,指针始终指向“正常”变量(如int,float ...),这些变量不是通过使用“new”创建的。谢谢。
答案 0 :(得分:4)
在C ++中实例化对象有两种主要方式:堆栈和堆(或免费存储)。例如:
void func()
{
// On the stack:
Widget blah;
// On the heap:
Widget * foo = new Widget;
delete foo;
}
堆栈对象/变量的优点是它们分配/访问的速度往往更快,而且它们更容易使用。但是,堆栈的大小有限,数据通常仅限于本地范围(全局变量除外,通常是不可取的)。也就是说,只要blah
结束,上面示例中的func()
对象就会自动销毁。你无能为力。因此,当原始项目超出范围时,任何指向堆栈对象/变量的指针都将变为无效(即“悬空”)。
堆(通常)更大,因此它可以处理比堆栈更多的数据。它往往稍微慢一点,但它的优点是让你在运行时重新分配东西。相比之下,堆栈对象/变量(尤其是数组)在编译时是固定的。
此外,在堆上分配了一个对象后,只要需要它就可以将它保留在那里,并保持对它的有效指针。在过去,您必须最终调用delete
以避免内存泄漏。在现代C ++中,鼓励使用智能指针(例如std::shared_ptr
)。
作为补充说明,在声明类成员时会稍微复杂一些。如果对象在堆栈上实例化,那么它的任何直接成员(即组合成员)也将在堆栈上。如果对象在堆上实例化,那么它的所有成员都将在堆上。
答案 1 :(得分:2)
我的问题是,为什么我们必须使用'new'在堆上创建SomeClass的实例?
你没有。您可以使用new动态创建对象。或者,您可以获得指向现有对象的指针
SomeClass* ptrMyClass1; // An uninitialized pointer.
// If an automatic object its value is indeterminate and
// You have not defined what it points at. It should not
// be used (until you explicitly set it to something).
// If a static object then it is initialized to NULL
// i.e. Global (or other static storage duration object).
SomeClass* ptrMyClass2 = new SomeClass; // A pointer to a dynamically
// allocated object.
SomeClass objMyClass3; // A normal object
SomeClass* ptrMyClass4 = &objMyClass3; // A pointer to a normal object
答案 2 :(得分:2)
有一种情况,你必须做这种事情。
当你使用没有具体方法的抽象类,以及从该抽象类继承的类时(在Java或PHP世界中,我们将讨论从interface
继承):
class IMyAbstractClass
{
public:
virtual int myFunction(void) = 0;
};
class MyInheritedClass : public IMyAbstractClass
{
public:
int myFunction(void)
{
// doSomething
return 0;
}
};
如果需要通过它们继承的抽象类来引用继承类的实例,那么语法是:
IMyAbstractClass * myInstance;
myInstance = new MyInheritedClass;
以这种方式声明对象之后,您可以将它作为IMyAbstractClass的实例传递给另一个对象的构造函数:
AnotherClass anotherObject(myInstance);
这个构造函数的编码如下:
class AnotherClass
{
public:
AnotherClass(IMyAbstractClass * instance)
{
// doSomething
}
};
Strategy design pattern中使用了这种行为。
答案 3 :(得分:1)
为什么我们必须使用'new'在堆上创建SomeClass的实例?
你不必须。您还可以引用在堆栈上创建的实例:
SomeClass some;
SomeClass* ptrMyClass(&some);