C++ 函数返回收缩向量中的字符。向量为空时返回什么?

C++ 函数返回收缩向量中的字符。向量为空时返回什么?,c++,vector,C++,Vector,我正在编写一个棋盘游戏,其中随机的棋子必须从袋子中取出(想象拼字游戏棋子从袋子中取出) 我使用以下函数从向量(表示行李)返回随机字符(表示碎片): 向量片段={'A','B','C','D','E','F'}; char pullPiece(){ int randomIndex=rand()%pieces.size(); char c=片段[randomIndex];//获取片段 片段.擦除(片段.开始()+随机索引);//删除片段 返回c; } 检索到字符后,它将从向量中删除。然后,函数返回

我正在编写一个棋盘游戏,其中随机的棋子必须从袋子中取出(想象拼字游戏棋子从袋子中取出)

我使用以下函数从向量(表示行李)返回随机字符(表示碎片):

向量片段={'A','B','C','D','E','F'};
char pullPiece(){
int randomIndex=rand()%pieces.size();
char c=片段[randomIndex];//获取片段
片段.擦除(片段.开始()+随机索引);//删除片段
返回c;
}
检索到字符后,它将从向量中删除。然后,函数返回检索到的字符

当向量
pieces
已删除其所有元素且为空时,处理调用
pullPiece()
的最佳方法是什么?


我能想到的唯一一件事就是抛出一个异常,但由于每次我玩游戏时都会发生这种情况,所以它看起来并不是一个异常。我还考虑过在调用
pullPiece()
之前检查向量的大小,但我觉得应该将此功能编程到
pullPiece()
函数本身。

在调用函数之前,可以检查向量是否为空


或者,在函数内部,检查向量是否为空并仅返回\0

一个非常简单的方法是为空案例返回
\0

从向量返回迭代器,而不是
char
,这可能值得重构。然后您可以安全地返回
碎片。end()
。这就是C++标准库容器的方式。请注意,您可以测试迭代器是否为
pieces.end()
,但不要尝试取消引用该迭代器,或对其进行递增。(只要容器不是空的,就可以将迭代器设置为
pieces.end()

类似于C的方法是重构函数以返回
int
,并为特殊值返回
EOF
。(参见
isupper
islower
等)

在新的std(c++17)中,有一个称为std::optional的东西。这意味着返回值可能存在,那么它只是您的字符,否则可以检查“invalibdit”。 boost还有一个可选类型

对于无效或负数,可以返回0


其他解决方案,如提供validflag作为引用并将其设置为有效,但我认为没有那么好。

您有一个函数需要返回一个字符,或者返回没有要返回的字符的信息。有不同的方法:

干净、笨拙且低效:如果没有要返回的字符,则抛出异常

清理,一点工作:有一个函数,告诉你一个字符是否可用,在你检索一个字符之前必须调用它。如果没有可用字符,则获取字符是一个必须修复并终止应用程序的错误

不干净,但高效:定义一个字符值以指示“没有可用数据”,例如“\0”。它在某些情况下比在其他情况下更有效。它可以在这里工作,因为可以返回的字符值只有一小部分。当您返回指向对象的指针或空指针时,它通常运行良好。如果任何返回值都是有效的,那么它根本不起作用

干净、高效,但不是在C++中:返回可选值。这就是可选的。(有人告诉我,optionals在一个新的标准中变得可用;使用它们。这就是optionals的用途)

干净、高效、略显笨拙:返回bool值表示调用成功。将char*或char&传递给它存放结果的函数(char&的优点是不能传递空指针;char*的优点是在源代码中很清楚char值将被修改)

干净、高效、略显笨拙:返回一个带有char值的struct,以及一个指示char值有效的bool(这实际上与返回可选值相同)

我个人更喜欢用支持它的语言返回可选值。否则,我更喜欢返回bool以获得成功,并通过指针返回值,因为这是一种始终有效的方法;为了任何一种价值

自己选择:

char pullPiece() noexcept; // 1) precondition: Pieces must be available.
char pullPiece();          // 2) Throws, if no piece is available.
std::optional<char> pullPiece() noexcept; // 3)
char pullpiect()无例外;//1) 前提条件:零件必须可用。
char pullPiece();//2) 如果没有可用的碎片,则抛出。
std::可选的PullPiect()无例外;//3)

在函数接口中有不同的方面需要考虑:

  • 简单吗
  • 是否有可能实现高效的实施
  • 目的明确吗?(我能做错什么吗?)
1) 显然,当要求客户机满足前提条件时,函数本身并不一定要检查它。(即使在调试版本中,强烈建议使用
assert()
)因此,接口1)允许最有效的实现

2) 这是最简单的接口。但是,客户机程序员必须阅读注释,以便知道如何处理空案例。那么,会出什么问题吗?是的,它可以。那很糟糕吗?不一定。但我会避免将异常作为正常控制流的一部分抛出

3) 第三个界面很清晰。没有什么会出错。它不再那么简单了,但是程序员不需要检查文档中的角落案例。从函数签名可以看出这一点。如果检查空性的开销不是很大的负担,那么我会选择这个解决方案


然而,请注意。已经有一些编译器,例如。GGCC4.9或clang 3.4都在C++14模式下。另一种方法是
boost::optional
,它甚至可以与较旧的编译器一起使用

您可能返回无效字符
char pullPiece() noexcept; // 1) precondition: Pieces must be available.
char pullPiece();          // 2) Throws, if no piece is available.
std::optional<char> pullPiece() noexcept; // 3)