初始化具有非默认构造函数的 std::array 项的更好方法?
Posted
技术标签:
【中文标题】初始化具有非默认构造函数的 std::array 项的更好方法?【英文标题】:Better way to initialise std::array item that has non-default constructor? 【发布时间】:2020-07-14 09:49:22 【问题描述】:目前在初始化 basicEnemies 数组 时,我需要将 audioManager 传递给每个 basicEnemy 类的构造函数。但是,我有 20 个基本敌人,所以有没有更好的方法来初始化 MainGameScene 中的每个 basicEnemy,而不必像我这样做的方式重复将 audioManager 传递给构造函数?需要调用每个 basicEnemy 的构造函数。
MainGameScene.h
MainGameScene(AudioManager *audioManager)
std::array<BasicEnemy, 20> basicEnemies;
MainGameScene.cpp
MainGameScene::MainGameScene(AudioManager *audioManager) : basicEnemiesaudioManager, audioManager, audioManager, audioManager...
BasicEnemy.h
BasicEnemy(AudioManager *audioManager)
如果在调用 MainGameScene 构造函数之后的 ':' 部分是什么或者它被称为什么不是太多,那么我下次可以更准确地问?
【问题讨论】:
"':' 部分是什么" - 它叫做member initializer list。对于您的实际问题-您确定数组是正确的数据结构吗?你总是有 20 个敌人活着吗?也许std::vector
会更合适?
可能的选项:1) 使用 std::vector
, std::array
无论如何在这里似乎很奇怪 2) 存储 std::unique_ptr<BasicEnemy>
而不是 3) 使 BasicEnemy
默认可构造
@Yksisarvinen 是的,总是有 20 个敌人活着,这永远不会改变,这就是选择数组的原因
根据定义,std::array 调用所有对象的默认构造函数。如果你不想要这个,那么使用 BasicEnemy 的向量怎么办?或者,您可以调整默认构造函数。
@SebastianHoffmann 1) basicEnemies 永远不会改变大小,所以数组是正确的吗? 2)您能否进一步扩展此 std::unique_ptr 以及它将如何与我当前的设置一起使用? 3)如果我在不同的场景中再次遇到这个问题,我想知道如何在没有默认构造函数的情况下做到这一点
【参考方案1】:
如果你坚持std::array<BasicEnemy>
数据成员,你可以使用额外的间接级别和std::index_sequence
:
class MainGameScene
private:
static constexpr std::size_t n_enemies = 20;
std::array<BasicEnemy, n_enemies> basicEnemies;
template<std::size_t... is>
MainGameScene(AudioManager* audioManager, std::index_sequence<is...>) :
basicEnemies(is, audioManager)...
public:
MainGameScene(AudioManager* audioManager) :
MainGameScene(audioManager, std::make_index_sequence<n_enemies>)
;
如果您可以放宽对数据成员类型的要求,以及std::shared_ptr
(在堆上分配),另一个选项是std::optional
(在自身内部存储一个对象):
class MainGameScene
private:
std::array<std::optional<BasicEnemy>, 20> basicEnemies;
public:
MainGameScene(AudioManager* audioManager)
std::fill(basicEnemies.begin(), basicEnemies.end(), audioManager);
;
【讨论】:
【参考方案2】:您可以生成它们:
MainGameScene::MainGameScene(AudioManager *audioManager)
std::generate(basicEnemies.begin(), basicEnemies.end(), [&audioManager]()
return BasicEnemy(audioManager);
【讨论】:
假设BasicEnemy
有一个默认构造函数。
此外,每个BasicEnemy
的构造函数仍在使用此策略调用(在生成之前)(尽管现在这是隐式的)。
我相信std::array
暗示容器类型或聚合初始化的默认构造函数,无论哪种方式,数组已经充满了元素;【参考方案3】:
为参数添加一个默认值,调用全局工厂函数:
BasicEnemy(AudioManager *audioManager = getAudioManager() )
【讨论】:
以上是关于初始化具有非默认构造函数的 std::array 项的更好方法?的主要内容,如果未能解决你的问题,请参考以下文章
编译器生成的默认构造函数是否会将std :: array中的指针初始化为nullptr?
为啥显式允许默认构造函数和具有 2 个或更多(非默认)参数的构造函数?