gpt4 book ai didi

c++ - 与C++中的对象数组混淆

转载 作者:IT老高 更新时间:2023-10-28 22:22:49 26 4
gpt4 key购买 nike

因此,我首先学习了Java,现在尝试切换到C++。我在使数组正常工作方面有些困难。

现在,我只是试图创建对象“Player”的数组,并用一个数组填充它。但是我得到一个错误。

Player* players = new Player[1];
players[0] = new Player(playerWidth, playerHeight, 20, 1);

错误提示:
操作数“=”与这些操作数匹配。操作数类型为:播放器=播放器*

我不明白为什么这行不通?

最佳答案

错误的意思是您正在尝试为变量分配错误类型的值。当错误显示Player = Player *时,这意味着左侧的变量是Player,而右侧的值是Player *

players[0] = new Player(playerWidth, playerHeight, 20, 1);

问题类似于您要执行的操作:
int x;
x = "Hello, World!";

左手和右手类型不匹配,并且没有自然转换,因此会出现错误。

第一个问题是您来自Java背景,Java经常使用指针,但对您隐藏了指针。 C++根本不会隐藏它们。结果是C++具有不同的语法来显式处理指针。 Java摆脱了所有这些,并主要使用C++中的常规非指针语法来处理指针。
Java:                                  C++:

Player player = new Player(); Player *player = new Player();

Player player2; Player *player2 = nullptr;

** no equivalent in java ** Player player3;

player.foo(); player->foo();

** no equivalent in java ** player3.foo();

** no equivalent in java ** *player;

** no equivalent in java ** &player2;

理解使用指针和直接使用对象之间的区别非常重要:
Java:                                  C++:

Player a = new Player(); Player *a = new Player();
Player b = a; Player *b = a;
b.foo(); b->foo();

在此代码中,只有一个对象,您可以通过 ab访问它,并且没有区别, ab都是指向同一对象的指针。
C++:

Player c = Player();
Player d = c;
d.foo();

在此代码中,有两个对象。它们是不同的,对 d进行操作不会影响 c

如果在Java中您了解了 int之类的“原始”类型与 String之类的对象类型之间的区别,那么一种思考的方式是在C++中所有对象都是原始的。如果我们回顾一下您的代码并使用“C++对象就像Java原语”规则,您可能会更好地发现问题所在:
Java:
int[] players = new int[1];
players[0] = new int(playerWidth); // huh???

应当明确指出,分配的右侧应该只是一个Player值,而不是动态分配新的Player对象。对于java中的int,它看起来像 players[0] = 100;。由于Java中的对象类型不同,因此Java无法像编写 int值那样编写对象值。但是C++确实可以。 players[0] = Player(playerWidth, playerHeight, 20, 1);
第二个问题是C语言中的数组很奇怪,而C++继承了它。

C和C++中的指针允许'指针算术。如果您有一个指向对象的指针,则可以对其进行添加或减去,然后获得指向另一个对象的指针。 Java没有与此类似的东西。
int x[2]; // create an array of two ints, the ints are 'adjacent' to one another
// if you take the address for the first one and 'increment' it
// then you'll have a pointer to the second one.

int *i = &x[0]; // i is a pointer to the first element
int *j = &x[1]; // j is a pointer to the second element

// i + 1 equals j
// i equals j - 1

另外,数组索引运算符 []可在指针上使用。 x[5]*(x+5)等效。这意味着指针可以用作数组,并且在C和C++中是惯用的和期望的。实际上,它甚至已经融入C++中。

在C++中,当您使用 new动态分配对象时,例如 new Player,通常会得到一个指向您指定类型的指针。在此示例中,您将获得 Player *。但是当您动态分配数组时,例如 new Player[5],不同。实际上,您没有获得指向第一个元素的指针,而是获得了由五个 Players组成的数组的指针。就像其他 Player *一样:
Player *p   = new Player;    // not an array
Player *arr = new Player[5]; // an array

唯一使此指针与众不同的是,当您对其进行指针算术运算时,将获得指向有效 Player对象的指针:
Player *x = p + 1;   // not pointing at a valid Player
Player *y = arr + 3; // pointing at the fourth array element

如果在没有保护的情况下使用 newdelete,将很难正确使用它们。为了证明这一点:
int *x = new int;
foo();
delete x;

此代码容易出错,并且可能是错误的。具体来说,如果 foo()引发异常,则 x会泄漏。

在C++中,每当您承担责任时(例如,当您调用 new时,您便承担了以后再调用 delete的责任时),您应该记住

R.A.I.I.
Responsibility* Acquisition Is Initialization



*人们经常说“资源获取是初始化”,但是资源只是一种责任。乔恩·卡尔布(Jon Kalb)在他的 Exception Safe C++演讲中说服我使用后一个术语。

R.A.I.I.意味着只要您承担了责任,就应该看起来像是在初始化一个对象;具体来说,您正在初始化一个特殊对象,该对象旨在为您管理该责任。这种类型的一个示例是 std::unique_ptr<int>,它将管理指向 int分配的 new的指针:
C++:

std::unique_ptr<int> x(new int);
foo();
// no 'delete x;'

要管理 Player数组,可以使用 std::unqiue_ptr,如下所示:
std::unique_ptr<Player[]> players(new Player[1]);
players[0] = Player(playerWidth, playerHeight, 20, 1);

现在 unique_ptr将为您处理该分配,您无需自己调用 delete。 (注:在分配数组时,应给 unique_ptr一个数组类型; std::unique_ptr<Player[]>;在分配其他任何东西时,都应使用一个非数组类型 std::unique_ptr<Player>。)

当然,C++具有更专业的R.A.I.I.用于管理数组的类型 std::vector,并且您应该更喜欢使用 std::unique_ptr:
std::vector<Player> players(1);
players[0] = Player(playerWidth, playerHeight, 20, 1);

或在C++ 11中:
std::vector<Player> players { Player(playerWidth, playerHeight, 20, 1) };

关于c++ - 与C++中的对象数组混淆,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14345031/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com