访问unique_ptr的多维向量中的对象方法

时间:2015-09-23 22:59:13

标签: c++ arrays multidimensional-array smart-pointers

我有一个初始化的对象的二维结构:

std::vector<std::shared_ptr<tile> > appearance;
for (int x = 0; x < building_data.x_width; x++)
    {
            appearance.push_back
            (std::shared_ptr<tile>(new tile[building_data.y_length]));
    }

现在,据我所知,访问瓷砖的成员函数的唯一方法是使用

appearance.at(x).get()[y].member_function()

令人困惑和麻烦,我觉得我错过了什么。

以前,我曾使用tile**来表示相同的结构和语法 tile[x][y]很不错,但原始指针很头疼。

那么,是否有更好的方法来访问数组中保存的对象的函数,其中数组中的第一个元素由向量中的智能指针指向?罗嗦,但它是我最好的。

3 个答案:

答案 0 :(得分:1)

首先,shared_ptr不适用于数组。当没有更多引用时,它会调用delete而不是delete[],如果托管对象是一个数组,则会导致未定义的行为。你可以阅读它here

至于访问shared_ptr对象,您可以使用operator*取消引用它。

另外,如果您知道向量的最终大小,则可能需要reserve一些空格以避免重新分配。

答案 1 :(得分:1)

您可以使用 - &gt;运算符以访问shared_ptr管理的对象的成员。它与原始指针使用的语法相同。

然而,正如Dantez的回答中提到的那样,你会遇到删除问题。

此外,看起来您正在构建某种类型的瓷砖板,也许是为了游戏?您是否考虑过使用1D向量和一些存取函数替换多维数组?

// board_width and height should be integers
std::vector<Tile> board;
board.reserve(board_width * board_height);
for (unsigned y_axis = 0; y_axis < board_height; ++y_axis)
{
    for (unsigned x_axis = 0; x_axis < board_width; ++x_axis)
    {
        board.push_back(Tile());
    }
}

...

vec2 index_to_coords(unsigned index)
{
    return vec2(index % board_width, index / board_width);
}

...

unsigned coords_to_index(const vec2& coords)
{
    return (static_cast<unsigned>(coords.y) * board_width) + static_cast<unsigned>(coords.x);
}

答案 2 :(得分:0)

我同意Fibbles,但有其他想法可以提供。即使在C语言中,Fibble的方法实际上也很常见,因为多维结构(矩阵)就这么简单。

但是,如果你坚持二维概念,你可以嵌套向量。考虑:

typedef std::vector< tile >     TileRow;
typedef std::vector< TileRow >  Tiles;

首先,这可能有点令人困惑,所以要明确创建:

std::vector< std::vector< tile > > t;

然而,使用typedef,那是

Tiles t;

现在,那是空的。要使用它,您需要推入一些行,并且对于每行推送一些列。你可能不喜欢这样,所以...你可以使用assign函数来设置一些行。例如,如果您需要10行乘10列的矩阵,则可以

t.assign( 10, TileRow( 10, tile() ) ); 

这假设tile具有默认构造函数,推送10行TileRow,每行包含10列默认构造的tile。

现在,t[ 1 ]返回对行1的引用。因此,t[ 1 ][ 1 ]是对位置1,1处的图块的引用,非常类似于数组。

然而,现在你没有分配/解除分配问题。

使用std :: array可以做类似的事情,甚至更好。

typedef std::array< tile, 10 >     TileRow;
typedef std::array< TileRow, 10 >  Tiles;

Tiles t;

此时,t已准备好使用默认的初始化磁贴。