C++ 在 try 块中创建对象,然后将它们存储在 std::array
C++ Create objects in a try bloc then store them in a std::array
我有一个 Player
对象,它可以在其构造函数中抛出异常,因此在我的主函数中,我在 try 块中创建了 2 个 Player
对象。
我想像这样将这 2 Player
存储在 std::array
中:
try
{
Player p1(10, 10, ikazuchi);
Player p2(70, 10, hibiki);
std::array<Player, 2> players = {p1, p2};
}
问题是我无法在 try 块之外使用数组,而且我听说将所有 main
代码放在 try 块中通常不是一个好主意。
我无法在 try 块之后声明我的 std::array
,因为 p1
和 p2
不再存在。
我可以用 std::vector
解决问题,但我读到,当我在编译期间知道数组的大小时,最好使用 std::array
。
我可以创建一个默认构造函数来创建我的对象,然后将它们填充到 try 块中,但在构造函数中创建所有内容似乎更合适。
最佳做法是什么?
您可以执行如下操作。
int main() {
std::array<int, 2> array;
try {
array[0]=1;
array[1]=1;
} catch (...) {
}
return 0;
}
使用Player
代替int
;
您总是可以使用动态分配或 boost::optional<std::array<Player, 2>>
之类的方法来解决此类问题,但真正的问题是:您应该这样做吗?也就是说,假设其中一个玩家对象无法构造并抛出异常。之后你将如何处理 players
数组?它不处于合法状态,或者至少不处于您期望的状态(如果没有抛出异常)。
try
的范围大一点没有问题。它应该涵盖所有异常会阻止您前进的地方。如果您不喜欢物理上有很多源代码,请将代码移到一个函数中。无论如何,这可能是个好主意:一个假设一切顺利的函数,另一个主要负责处理错误的函数。
并且如果当内部对象处于无效状态(构造函数抛出)时您有继续使用 players
的有意义的方法,那么您可以首先创建包含处于该状态的对象的数组(在 try
块之外),只需在 try
.
内部分配它们
问题表明您不想提供不需要的默认构造函数,但我声称 player
属于 try
,或者 Player
需要默认构造函数(或表达“未正确初始化”的等效方式。
如果你的玩家 csn 是 copied/moved 并且构造简单,只需创建数组并分配给它。
std::array<Player, 2> players;
try{
players[0]=Player(10, 10, ikazuchi);
players[1]=Player(70, 10, hibiki);
} catch ...
或者你可以这样做:
std::optional<std::array<Player, 2>> players;
try{
Player p1(10, 10, ikazuchi);
Player p2(70, 10, hibiki);
players.emplace(std::array<Player, 2>{{std::move(p1),std::move(p2)}});
} catch ...
但您可能需要找到非 C++17 版本的可选,例如 boost 可选。
另一种方法是:
auto players = [&]()->std::array<Player, 2>{
try {
Player p1(10, 10, ikazuchi);
Player p2(70, 10, hibiki);
return {{std::move(p1),std::move(p2)}};
} catch (some_error){
throw some_other_error;
}
}();
但因此需要通过数组或抛出退出。
我有一个 Player
对象,它可以在其构造函数中抛出异常,因此在我的主函数中,我在 try 块中创建了 2 个 Player
对象。
我想像这样将这 2 Player
存储在 std::array
中:
try
{
Player p1(10, 10, ikazuchi);
Player p2(70, 10, hibiki);
std::array<Player, 2> players = {p1, p2};
}
问题是我无法在 try 块之外使用数组,而且我听说将所有 main
代码放在 try 块中通常不是一个好主意。
我无法在 try 块之后声明我的 std::array
,因为 p1
和 p2
不再存在。
我可以用 std::vector
解决问题,但我读到,当我在编译期间知道数组的大小时,最好使用 std::array
。
我可以创建一个默认构造函数来创建我的对象,然后将它们填充到 try 块中,但在构造函数中创建所有内容似乎更合适。
最佳做法是什么?
您可以执行如下操作。
int main() {
std::array<int, 2> array;
try {
array[0]=1;
array[1]=1;
} catch (...) {
}
return 0;
}
使用Player
代替int
;
您总是可以使用动态分配或 boost::optional<std::array<Player, 2>>
之类的方法来解决此类问题,但真正的问题是:您应该这样做吗?也就是说,假设其中一个玩家对象无法构造并抛出异常。之后你将如何处理 players
数组?它不处于合法状态,或者至少不处于您期望的状态(如果没有抛出异常)。
try
的范围大一点没有问题。它应该涵盖所有异常会阻止您前进的地方。如果您不喜欢物理上有很多源代码,请将代码移到一个函数中。无论如何,这可能是个好主意:一个假设一切顺利的函数,另一个主要负责处理错误的函数。
并且如果当内部对象处于无效状态(构造函数抛出)时您有继续使用 players
的有意义的方法,那么您可以首先创建包含处于该状态的对象的数组(在 try
块之外),只需在 try
.
问题表明您不想提供不需要的默认构造函数,但我声称 player
属于 try
,或者 Player
需要默认构造函数(或表达“未正确初始化”的等效方式。
如果你的玩家 csn 是 copied/moved 并且构造简单,只需创建数组并分配给它。
std::array<Player, 2> players;
try{
players[0]=Player(10, 10, ikazuchi);
players[1]=Player(70, 10, hibiki);
} catch ...
或者你可以这样做:
std::optional<std::array<Player, 2>> players;
try{
Player p1(10, 10, ikazuchi);
Player p2(70, 10, hibiki);
players.emplace(std::array<Player, 2>{{std::move(p1),std::move(p2)}});
} catch ...
但您可能需要找到非 C++17 版本的可选,例如 boost 可选。
另一种方法是:
auto players = [&]()->std::array<Player, 2>{
try {
Player p1(10, 10, ikazuchi);
Player p2(70, 10, hibiki);
return {{std::move(p1),std::move(p2)}};
} catch (some_error){
throw some_other_error;
}
}();
但因此需要通过数组或抛出退出。