我是来自Java的c++程序员的新手,我喜欢c++。据我所知,我认为指针通常指向已经初始化的对象的地址。在coocos2d中,为了创建一个对象,你经常会写一些东西:
auto mysprite=Sprite::create("image.png");
要使用Mysprite的方法,您可以编写:
mysprite->mymethod();
我对指针的基本知识是,它们的使用方式如下:
int* mypoint;
int x=7;
mypoint=&x;
来自Java,这很令人困惑,为什么不或什么时候创建这样的对象,像这样调用类本身:
Sprite* mysprite=Sprite::create("image.png");
mysprite.mymethod();
我认为这很重要,因为 cocos2d 库中的许多构造函数在构造函数中接受指针,我发现自己盲目地将 auto 作为变量的标识符,但我不知道为什么。感谢您提前澄清。
我的问题是为什么我要使用"->"而不是".">
因为左边的东西是一个指针。
如果a
是指针,那么a->b
与(*a).b
相同,只是看起来更好。
如果a
是指针,则a.b
是错误。
在C++中,指针与Java中的对象引用(又名对象)占据的位置大致相同。在 Java 中,您可以执行以下操作:
String foo = new String;
当你这样做时,foo
实际上是引擎盖下的指针。例如,您可以执行此操作:
String foo = new String;
String bar = foo;
这不会创建String
的副本,它只是设置bar
引用与 foo 相同的String
。对于String
来说,这不是一个重要的区别,因为Java中的String
类型是不可变的。但是,对于这样的事情:
int[][] foo = new int[5][5];
int[][] bar = foo;
bar[0][0] = 6;
那么它很重要。设置bar[0][0]
时,也会设置foo[0][0]
因为它们引用同一个数组。bar
和foo
是对某事的引用,而不是价值观。在 Java 中,这有点模糊,因为您唯一可以拥有的值是原始类型,如int
或float
。
在C++中,可以具有复杂类型的值。例如,如果你这样说:
struct point_2d {
int x, y;
};
void a_function()
{
point_2d p1;
point_2d p2 = p1;
p2.x = 5;
}
首先,注意缺乏new
。在C++中,new
用于创建"堆上"的东西,这是Java放置所有非原始类型的地方。在C++中,p1
和p2
在同一个地方,Java会把int x;
和int y;
放在同一个地方。在堆栈上。它们在函数退出时被销毁,而不是因为对它们的所有引用都消失了,所以它们被垃圾回收。无论如何,它们都会消失。
此外,当您执行p2.x = 5;
时,p1.x
的值没有改变。创建p2
时,您从p1
复制了该值。您没有创建对它的另一个引用。因此,这些值彼此独立存在。
现在,为什么你的图书馆到处扔指针?嗯,C++中的指针就像Java引用(换句话说,Java中每个不是基元类型的变量)。但是,由于C++中的默认值不是引用(与Java不同),因此您必须明确何时拥有引用,何时没有引用。
在您的特定情况下,在Sprite::create
函数内的某个地方,库正在执行类似Sprite *newsprite = new Sprite;
.因此,它正在堆上创建一个Sprite
。很可能,它实际上是一个派生自Sprite
的类,而不是Sprite
本身,而是相同的基本思想。
您一直必须使用->
而不是.
,因为->
用于通过指针访问类的成员,而.
用于通过值访问它们。由于Java没有这种区别(任何你使用.
的东西都已经是一个指针了),它没有两种不同的语法。
这意味着您必须在某个时间点执行delete mysprite;
以释放它正在使用的内存。与 Java 不同,C++ 不会为您进行内存管理(也称为垃圾回收)。
您正在使用的这个 cocos 2d-x v3 库似乎也有一个相当老式的界面。在现代C++由于各种不同的原因,不鼓励您使用裸指针。该库应返回::std::shared_ptr<Sprite>
或::std::unique_ptr<Sprite>
。但这超出了这个问题的范围。
但是,库必须使用指针。复制Sprite
可能相当昂贵(特别是因为库似乎使用的是较旧的接口样式,因此可能没有利用诸如移动构造函数之类的漂亮功能),因此库希望在堆上分配一个并传递一个引用(又名指针),因为这些复制成本很低。
另外,在你了解发生了什么之前,尽量不要使用auto
。C++的自动类型推断在各种情况下都非常好,尤其是在使用容器类时,这些容器类有时可能具有非常复杂的迭代器等类型名称。但它允许你在不使用类型的情况下使用类型,而不必真正知道你正在使用哪些类型。就你而言,以你的经验水平,你尝试使用的库,这不是很好。
这个话题对于StackOverflow的答案来说真的太复杂了。但这是正在发生的事情的基础,应该提供