如何在C++中返回二维字符数组?

10

我在函数内创建了一个二维数组,我想返回这个数组,并将它传递到其他函数中。

char *createBoard( ){  
  char board[16][10];
  int j =0;int i = 0;
  for(i=0; i<16;i++){
        for( j=0;j<10;j++){   
                board[i][j]=(char)201;
        }   
  }
  return board;
}

但是这一直给我报错


你能更具体地描述一下错误吗? - James L
1
你应该使用无符号字符(unsigned char),因为201不在字符(char)的范围内。 - Dave Van den Eynde
2
此外,您正在返回局部变量的地址。如果尝试访问它,程序将崩溃。 - Naveen
8个回答

11

你正在做的是返回指向在堆栈上创建的对象(名为board的数组)的指针。当该数组超出作用域时,它将被销毁,因此指针不再指向任何有效的对象(悬空指针)。

你需要确保该数组是在堆上分配的,使用new关键字进行动态内存分配。在现代C++中创建动态分配数组的标准方法是使用std::vector类,尽管这对于创建2D数组来说更加复杂。

char **createBoard()
{
    char **board=new char*[16];
    for (int i=0; i<16; i++)
    {
       board[i] = new char[10];
       for (int j=0; j<10; j++)
         board[i][j]=(char)201;
    }

    return board;
}

void freeBoard(char **board)
{
    for (int i=0; i<16; i++)
      delete [] board[i];
    delete [] board;
}

是的,对不起,我当时没有坐在编译器旁边,只能猜测那行代码的语法。 - 1800 INFORMATION
1
我已经添加了一些关于free函数的细节并修复了语法错误。我想提到这种风格并不是真正的经典C++,它更像是C风格 - 在C++中正确的做法应该涉及一个数组类,比如vector - 这就是为什么Neil的答案被高度投票的原因。 - 1800 INFORMATION
1800 INFORMATION,您能否解释一下为什么在这里使用“类”相比于您的方法更好? - bit-question
使用标准容器类,如vector更加简洁和安全。看看我代码中所有的内存管理代码和指针操作——这会增加复杂性,并使引入错误的可能性更大。 - 1800 INFORMATION
注意 char *board[16]char (*board)[16] 之间的区别。前者是指针数组,而后者是指向包含16个字符的数组的指针。在大多数代码中,这并不重要,但它可能很关键。例如,如果board是一个二维字符数组,则 char *xx = (char*) board; xx [17] ='A' 将按预期工作,但如果它是一个 char * 数组,则不会。其中一个关键问题出现在全局变量和外部声明 - 它们需要匹配。 - ash
显示剩余3条评论

11
最好的方法是创建一个棋盘类,并将ctreateBoard函数作为其构造函数:
class Board {
  private:
   char mSquares[16][10];

   public:
    Board() {
        for(int i=0; i<16;i++){
        for( int j=0;j<10;j++){   
                mSquares[i][j]=201;
        }       
    }

   // suitable member functions here
 };

关于如何使用这样的类,没有什么比阅读一本好书更好的替代品了。我强烈推荐阅读 Andrew Koenig 和 Barbra Moo 的 Accelerated C++


我该如何将它传递给其他类的另一个函数? - r4ccoon
一个简单的方法是将mSquares标记为public。并将Board对象的引用传递给函数。 - Benoît
为什么这是一种不好的方式?请详细阐述。 - bit-question

2
我建议您在此使用STL vector<>或boost/multi_array容器。如果必须使用数组,则我建议使用typedef来定义数组。
typedef char[16][10] TBoard;

您也可以返回

 char**

...但是你需要将它强制转换为正确的大小,才能正确地对其进行索引。C++不支持动态多维数组。

另外,正如其他人所建议的那样,你不能返回堆栈上的对象(即局部变量)。


无法使用Boost框架,而且他们也没有教我关于向量的知识,所以我不能使用它。 - r4ccoon
如果您有一个静态的板子大小,那么请使用typedef。 - Anders Hansson

2

这种方法行不通。如果你返回一个指向局部变量的指针,那么会遇到未定义的行为。相反,应该使用new在堆上分配一个数组,并手动将数据复制到其中并进行索引。


1
不要返回指向局部变量的指针,正如其他人所提到的。如果我被迫实现你想要的功能,首先我会选择使用std::vector。既然你还没有学习std::vector,这里有另一种方法:
void createBoard(char board[16][10])
{  
  int j =0;int i = 0;
  for(i=0; i<16;i++){
        for( j=0;j<10;j++){   
                board[i][j]=(char)201;
        }       
  }
}

2
应该是 "void createBoard(char (&board)[16][10]);"(数组的引用)。 - qwerty
1
qwerty的观点是:你将参数定义为传值调用(pass-by-value)。如果改为引用调用(pass by reference),一切都会很好。 - xtofl
他们都在使用Visual Studio 2008。我很困惑,我的实现有什么问题?数组是如何按值传递的? - Donotalo

0
你应该返回char**而不是char*

尝试这样做,将我的网格定义更改为 char board [16] [10]; 并将board [i] [j] =(char)201;分配给它, 仍然会生成编译器错误。 - r4ccoon

0

对你的问题的简单回答是char**。

话虽如此,不要这样做! 你的“board”变量在createBoard()之外不会持续存在。

使用boost::multi_array并将其作为引用传递给createBoard()或直接返回它(但如果你这样做,它将被复制)。


0

你不能返回指向函数局部变量的指针,因为一旦函数返回,该空间就会被覆盖。

与board关联的存储空间位于函数的栈上。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接