首页 > 解决方案 > 带智能指针的段错误

问题描述

我目前正在尝试使用智能指针,但在尝试访问 getColor() 时遇到了段错误?

有人能说出我错过了什么吗?(对于理解板的定义如下:std::unique_ptr board [HEIGHT][WIDTH];)

std::unique_ptr<Piece> current (new Pawn(Color::WHITE));
this->board[1][1] = std::move(current);
        
if(this->board[1][1].get() == nullptr){
    Log::debug("is nullptr");
    return;
}

if(this->board[1][1].get()->getColor() == Color::BLACK){
    Log::debug("Black");
} else{
    Log::debug("White");
}

谢谢

标签: c++smart-pointers

解决方案


你的问题没有提供很多细节。但是我能够对其进行编码并在没有段错误的情况下运行它。

https://godbolt.org/z/5Ehfe7

#include <memory>
#include <fmt/core.h>

constexpr std::size_t HEIGHT {8};
constexpr std::size_t WIDTH {8};

enum class Color {
    WHITE, BLACK
};

struct Piece {
    explicit Piece(Color color) : color_(color) {}
     Color getColor() const {
        return color_;
    }
        Color color_;
};
struct Pawn : public Piece {
    explicit Pawn(Color color) : Piece(color){

    }
};

struct Board {
std::unique_ptr<Piece> board [HEIGHT][WIDTH];
  void set() {
    std::unique_ptr<Piece> current(new Pawn(Color::WHITE));
    this->board[1][1] = std::move(current);

    if (this->board[1][1].get() == nullptr) {
      fmt::print("is nullptr");
      return;
    }

    if (this->board[1][1].get()->getColor() == Color::BLACK) {
      fmt::print("Black");
    } else {
      fmt::print("White");
    }
  }
};

int main() {
    Board b;
    b.set();
}

更新

这是一个我更喜欢的版本:https ://godbolt.org/z/z6rfav

变体与继承

我没有继承Piece,而是制作PieceTypestd::variant所有可能类型的棋子(Pawn,Queen,King,...)。这是可能的,因为这组片段是封闭的:我们在编译时知道所有可能的片段。

enum class Color { WHITE, BLACK };

struct Pawn {};
struct King {};

using PieceType = std::variant<Pawn, King>;  // extend to all pieces

struct Piece {
  Piece(PieceType type, Color color) : color_(color), type_(type) {}
  Color getColor() const { return color_; }
  Color color_;
  PieceType type_;
};

std::arrayvs 不安全的 C 数组

我将boardfrom的定义切换std::unique_ptr<Piece> board[8][8]std::array<std::array<Piece, 8>, 8>。这是更安全、更惯用的 C++。

空指针与可选

而不是使用 unique_ptr 来表示字段是否为空。我用std::optional.

  std::array<std::array<std::optional<Piece>, WIDTH>, HEIGHT> board_;

// Could be written as 
using Field = std::optional<Piece>;
using Row = std::array<Field, WIDTH>;
using Board = std::array<Row, HEIGHT>;
Board board_;

推荐阅读