【问题标题】:How to initialize static member array with a result of a function?如何用函数的结果初始化静态成员数组?
【发布时间】:2015-10-14 23:37:39
【问题描述】:

我正在将this Python 文件的此类片段翻译成 C++:

SIDE = 3
LINES = []
for y in range(SIDE):
    row = tuple((x, y) for x in range(SIDE))
    LINES.append(row)
for x in range(SIDE):
    col = tuple((x, y) for y in range(SIDE))
    LINES.append(col)
LINES.append(tuple((x, x) for x in range(SIDE)))
LINES.append(tuple((SIDE - x - 1, x) for x in range(SIDE)))

LINES 保存井字游戏中可能线条的 (x, y) 坐标。所以对于SIDE = 3 它成立:

[((0, 0), (1, 0), (2, 0)), 
 ((0, 1), (1, 1), (2, 1)), 
 ((0, 2), (1, 2), (2, 2)), 
 ((0, 0), (0, 1), (0, 2)), 
 ((1, 0), (1, 1), (1, 2)), 
 ((2, 0), (2, 1), (2, 2)), 
 ((0, 0), (1, 1), (2, 2)), 
 ((2, 0), (1, 1), (0, 2))]

SIDE 值可以更改。

我尝试过的

性能至关重要(这就是我使用 C++ 的原因),所以我只想计算一次 LINES。因此,我选择将LINES 实现为TicTacToeState 类的静态成员。

我从这样的代码开始:

static char init_lines() {
    return 'a';
}

class TicTacToeState {
    static char LINES;
};

char TicTacToeState::LINES = init_lines();

它有效。如何将LINES 更改为数组?也许矢量会更好?有双吗?

也许静态成员不是最好的选择,也许有更简单的方法?

你会如何把它翻译成 C++?

我们知道LINES 的大小,它总是2 * SIDE + 2.

特殊要求

所有 C++ 代码必须在一个 .cpp 文件中,没有标题。为什么?因为这是机器人竞赛库的片段,通常您只能提交一个文件。

【问题讨论】:

标签: c++ arrays static initialization


【解决方案1】:

在 C++ 中,您可以使用组初始化来初始化静态数组成员

    static int a[10] = {5}; //this will initialize first position item with 5 and rest with 0s
    static char b[2] = {'b', 'b'};
    static int c[2][2] = { {1,1}, {1,2} };

    int main()
    {
        cout<< a[0] << endl; //output: 5
        cout<< a[1] << endl; //output: 0

        cout<< b[0] << endl; //output: b

        cout<< c[0][1] << endl; //output: 1
    }

虽然事实是你需要知道数组的大小不像 Python 的动态列表那样


如果您需要将动态计算的值插入到表中,最好的方法是创建工厂方法

    static int** fact(int width, int height)
    {
        int** a;

        a = new int*[width]; //we can do it when it is DYNAMIC array! 

        a[0] = new int[height];
        a[1] = new int[height];

        for(int i = 0; i < width; i++)
            for(int k = 0; k < height; k++)
                a[i][k] = i*k;

        return a;
    }

    static int** c = fact(2, 2); //you can call it with your SIDE var

    int main()
    {
        cout<< c[1][1] << endl; //output: 1
    }

当然可以循环处理

当您决定使用与 Python 的动态列表等效的 std Vector 类时,同样的方法将是正确的

【讨论】:

  • 还有一个更大的问题——我不能用 { } 数组初始化器和其中给出的常量值来初始化它。正如您在 Python 代码中看到的,我需要根据 SIDE 值动态计算坐标。
  • 你为什么不使用vector
  • 如果使用v[i] 语法,访问vector 的元素与访问数组元素一样快。区别在于分配和解除分配的时间,但如果在编译时不知道大小,则无法避免。
  • @m.antkowicz 基于堆栈的(或静态)数组比std::vector 更快,因为您不必分配内存为他们。 (请注意,您可以使用std::array,它在这种情况下具有相同的性能。)一旦您使用new,您就可以使用std::vector,以相同的成本但没有所有麻烦。
  • @m.antkowicz 它们在访问/写入性能上应该相当。毕竟,一个向量是作为一个动态分配的数组来实现的。仅当您将其大小调整到已在内存中保留的大小之上时,它才会变慢。但话又说回来,您实际上并没有数组本身具有该功能。
【解决方案2】:

我想你可以像这样使用 lambda 函数来做到这一点:

#include <vector>
#include <iostream>

const auto SIDE = 3U;

struct coord
{
    unsigned x;
    unsigned y;
    coord(unsigned x, unsigned y): x(x), y(y) {}
};

static const auto lines = [] // lambda function
{
    // returned data structure
    std::vector<std::vector<coord>> lines;

    for(auto y = 0U; y < SIDE; ++y)
    {
        lines.emplace_back(); // add a new line to back()
        for(auto x = 0U; x < SIDE; ++x)
            lines.back().emplace_back(x, y); // add a new coord to that line
    }

    for(auto x = 0U; x < SIDE; ++x)
    {
        lines.emplace_back();
        for(auto y = 0U; y < SIDE; ++y)
            lines.back().emplace_back(x, y);
    }

    lines.emplace_back();
    for(auto i = 0U; i < SIDE; ++i)
        lines.back().emplace_back(i, i);

    lines.emplace_back();
    for(auto i = 0U; i < SIDE; ++i)
        lines.back().emplace_back(SIDE - i - 1, i);

    return lines;
}(); // NOTE: () is important to run the lambda function

int main()
{
    for(auto const& line: lines)
    {
        std::cout << "(";
        for(auto const& coord: line)
            std::cout << "(" << coord.x << ", " << coord.y << ")";
        std::cout << ")\n";
    }
}

输出:

((0, 0)(1, 0)(2, 0))
((0, 1)(1, 1)(2, 1))
((0, 2)(1, 2)(2, 2))
((0, 0)(0, 1)(0, 2))
((1, 0)(1, 1)(1, 2))
((2, 0)(2, 1)(2, 2))
((0, 0)(1, 1)(2, 2))
((2, 0)(1, 1)(0, 2))

【讨论】:

    猜你喜欢
    • 2012-07-16
    • 1970-01-01
    • 2011-08-04
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-09-01
    • 1970-01-01
    相关资源
    最近更新 更多