将指向多维数组向量中的单个项的指针传递给函数 c++

Passing pointer to single item in Vector of Multidimensional Array to Function c++

本文关键字:指针 单个项 c++ 函数 向量 数组      更新时间:2023-10-16

我正在使用 SDL 开发一个程序。我在主函数之外实例化了以下变量:

std::vector<SDL_Rect[TOTAL_ACTIVITIES][TOTAL_DIRECTIONS][ANIMATION_FRAMES]> gPersonSpriteClips;

(其中全大写项是常量整数(。这是一个数组的向量,因为我打算稍后做很多精灵开发。现在,我只有几个占位符精灵。因此,3D 数组捕获了单个人体类型精灵表的所有方面,当我拉入表时,我会让代码将其拆分为多种体型......

我有一个类"Character",它在准备渲染时利用数组。以下是在main中渲染myCharacter的调用:

myCharacter.render(bodySpritesheetTexture, &*gPersonSpriteClips[myCharacter.getBody()]);

Character.getBody(( 返回此字符实例使用的正文类型的向量索引。下面是 Character.h 中的函数声明:

void render(LTexture& characterSpriteSheetTexture, SDL_Rect spriteClips[TOTAL_ACTIVITIES][TOTAL_DIRECTIONS][ANIMATION_FRAMES]);

下面是 Character.cpp 中的函数本身:

void Character::render(LTexture& characterSpriteSheetTexture, SDL_Rect spriteClips[TOTAL_PERSON_ACTIVITIES][TOTAL_CARDINAL_DIRECTIONS][PERSON_ANIMATION_FRAMES])
{
characterSpriteSheetTexture.render( mPosition.x, mPosition.y, &spriteClips[mActivity][mDirection][mAnimations[mActivity][mCurrentFrame]] );
}

mActivity 是角色"当前正在执行的活动"的枚举。 mDirection是他面对的方向。 mAnimations 列出了帧顺序(因为其中一些动画以不同的顺序多次使用相同的精灵(。

最后,LTexture 的渲染函数直接取自 LazyFoo 的 SDL 教程。

characterSpriteSheetTexture.render(( 调用具有以下声明的函数(在 LTexture.h 中(:

void render( int x, int y, SDL_Rect* clip = NULL, int targetHeight = NULL, int targetWidth = NULL, double angle = 0.0, SDL_Point* center = NULL, SDL_RendererFlip flip = SDL_FLIP_NONE );

所以它期待一个 SDL_Rect* 剪辑类型的参数。该函数调用:

SDL_RenderCopyEx( gRenderer, mTexture, clip, &renderQuad, angle, center, flip );

编译代码时出现错误,将我指向 SDL 库中的某个位置。我已经成功地使用了 LTexture 的渲染函数,将索引从一维数组SDL_Rect传递到其中,所以我非常有信心这个问题存在于我的向量参数中。

忽略关于命名约定的分歧......我在这里做错了什么,实现我想要做的事情的正确方法是什么?

当然,我将来可能会大大简化我的动画方案;这是我第一次尝试生成玩家角色。无论如何,我想知道在这种情况下出错的机制。

最后,请不要建议我使用boost。我真的很想避免这个程序的提升。

伊塔:

以下是 Character.h 中 mAnimation 的声明:

std::vector<int> mAnimations[TOTAL_ACTIVITIES];

下面是它在默认构造函数中的初始化:

for (int i = 0; i < TOTAL_ACTIVITIES; i++)
{
mAnimations[i].resize(ANIMATION_FRAMES);
for (int j = 0; j < ANIMATION_FRAMES; j++)
{
mAnimations[i][j] = j;
}
}

像这样更改全局数组定义:

using SdlRectArray = std::array<std::array<std::array<SDL_Rect, ANIMATION_FRAMES>, TOTAL_DIRECTIONS>, TOTAL_ACTIVITIES>;
std::vector<SdlRectArray> gPersonSpriteClips;

请参阅此处,了解为什么不将数组存储在std::vector或任何其他容器中

因此,请按如下方式定义Character::render()方法:

void render(LTexture& characterSpriteSheetTexture, SdlRectArray& spriteClips)
{
characterSpriteSheetTexture.render( mPosition.x, mPosition.y, &spriteClips[mActivity][mDirection][mAnimations[mActivity][mCurrentFrame]] );
}

然后你可以这样称呼它:

myCharacter.render(bodySpritesheetTexture, gPersonSpriteClips[myCharacter.getBody()]);

因为没有必要做&*.

很难从您的问题中判断确切的错误是什么,但似乎根本原因可能是"数组衰减"。

在C++(和 C 中(中,数组参数几乎总是被视为指向数组开头的指针。 对于多维数组,这意味着您期望的多索引无法工作,因为该语言已经剥离了必要的大小和形状信息。

唯一的例外是参考参数不会以这种方式衰减。 但是,如果您依赖它,您(以及处理您的代码的任何其他人(将需要记住每次将多维数组传递给另一个函数时都使用该确切的引用参数。

在现代C++中,此问题通常使用std::array<>修复,这是为此目的而设计的。 在您的情况下,这将非常冗长,所以我建议使用类型别名:

typedef std::array< std::array< std::array<SDL_Rect,
ANIMATION_FRAMES>, TOTAL_DIRECTIONS>, TOTAL_ACTIVITIES> SpriteClip;
std::vector<SpriteClip> gSpriteClips;

或者,你可以写一个简短的类:

class SpriteClip {
SDL_Rect m_data[TOTAL_ACTIVITIES][TOTAL_DIRECTIONS][ANIMATION_FRAMES];
public:
SDL_Rect& get(activity, direction, frame) {
return m_data[activity][direction][frame];
}
};

这样,您就可以轻松更改表示形式 - 例如,如果您决定希望不同的精灵具有不同数量的活动和帧。