【问题标题】:Is it allowed to insert a null value into a C++ std::map?是否允许在 C++ std::map 中插入空值?
【发布时间】:2013-02-20 19:20:40
【问题描述】:

我正在考虑棋盘设计,并想做一些类似的事情:

typedef std::map <std::string, CheckerPiece> MapType;
MapType CheckerBoard;

CheckerBoard.insert({"a1", null});

这是允许的,还是有办法做类似的事情?这个想法是我想保持棋盘状态,同时将 CheckerPiece 对象从一个位置移动到另一个位置。

编辑: 同样,是否可以执行以下操作:

CheckerBoard.insert({"a1", new CheckerPiece()});

【问题讨论】:

  • 你想要一个字符串到指针的映射吗?
  • 这是不允许的。作为一种解决方法,您可以使用像 Boost.Optional 这样的包装类型 - 这比指针更受欢迎。
  • 你应该改变你的设计,这样你就不需要在容器中有 NULL 条目。请参阅下面的答案。

标签: c++ std stdmap


【解决方案1】:

您的地图不包含CheckerPiece 指针,因此您尝试执行的操作甚至无法编译,除非您有一个将指针作为参数的CheckerPrice 的隐式构造函数。这忽略了nullC++ 中没有任何意义的事实。假设你的意思是 NULLnullptr,你不能插入其中任何一个,或者

new CheckerPiece()

进入你的地图,期间。上面的表达式返回一个指向CheckerPiece的指针。

C++ 没有空值类型的概念(除非您专门设计了一个)。一种解决方法是使用为您提供可选语义的包装器类型,即允许您检查是否已“设置”某些内容。一个例子是boost::optional

这是一个未经测试的例子:

#include <boost/optional.hpp>

boost::optional<CheckerPiece> piece;

if (piece) {
  // piece is not set, we should never get here
}

piece.reset(CheckerPiece( constructor arguments...));

if (piece) {
  // piece is set, use it!
  piece.move();
}

【讨论】:

  • 感谢您的洞察力。我想我可能只是为每个元素添加一个 CheckerPiece 并创建一个成员 bool isActive 来打开和关闭它们。我不想在这方面变得太复杂 - 除非您可以使用 boost 库提供一个快速示例?
  • @ctote 我添加了一个示例。没测试过,可能有语法错误但大体原理是可以的。
【解决方案2】:

CheckerPiece 是什么样的?最明显的解决方案 将是添加一个额外的可能性对应于 没有一块。碎片真的没有任何行为,并且 你不需要它们;你真的只需要 关于正方形状态的信息:红色、黑色或 空,加冕与否(如果为空,则忽略)。

我可能会补充一点,将棋盘作为地图可能不是 最精明的解决方案。我会选择类似的东西:

CheckerPiece board[10][10];

(或CheckerPiece board[N][N],其中N是一个模板 参数,如果您想支持本地变体,而不仅仅是 国际标准检查器)。

【讨论】:

    【解决方案3】:

    如果您想使用指针/堆分配的 CheckerPieces,您必须将映射定义为使用 CheckerPiece* 而不是 CheckerPiece。 C++ 中没有 null 这样的东西作为“这里没有对象”的值。在不使用第三方库的情况下指示可选对象的规范方法是使用指针并将其设置为nullptr(如果可选元素不存在)。

    我可能会使用 boost::optional 来表示 CheckerPiece 可能位于或可能不在给定位置,除非您有不能使用第三方库的原因。

    【讨论】:

    • 没有真正的理由我不能使用第三方,但对于这种简单的情况,我宁愿避免使用它。你是说我可能会做一些类似的事情: typedef std::map <:string checkerpiece> MapType;地图类型棋盘; CheckerBoard.insert({"a1", nullptr});
    • 是的,这就是我想说的。
    【解决方案4】:

    更改您对董事会的定义。

    板或板状态是&lt;checker piece, location&gt; 的集合。不在此容器中的任何棋盘位置均被视为空。任何不处于棋盘状态的检查器都已被捕获。

    有了这个概念,就不需要一个空检查块,也不需要比较一个检查块是否为 NULL。

    在计划移动或创建移动历史时,您可以使用棋盘状态容器。

    我建议创建将使用给定板状态绘制板的函数。这免除了尝试从棋盘状态容器中表示每次移动时的实际棋盘的问题。

    【讨论】:

      猜你喜欢
      • 2014-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-31
      • 2013-11-19
      • 2010-09-10
      • 1970-01-01
      相关资源
      最近更新 更多