范围,数组和堆

时间:2009-07-10 06:26:24

标签: c++ pointers scope

所以,我有这个数组。需要在此函数范围之外访问它。我一直把它的指针打成一对放入双端队列的指针。但是一旦我超出范围,本地堆栈就会消失,数组无效,我只是有一个无用的指针,对吗?

所以我试图把这个数组放到范围超越堆上,它将一直存在,直到我以后删除它。但是我在解决这个问题上遇到了问题。现在g ++正在咳嗽从'int'到'int *'的无效转换错误。

void randomFunction(int x, int y, int width, int height)
{
  int **blah[4] = {x, y, width, height};
  std::pair <foobar*, int* > tempPair (foobar1, blah);
  randomDeque.push_front(tempPair);
}

我也试过像这样初始化它:

int *blah[4] = new int[4];

...并且它表示必须使用括号括起的初始化程序初始化数组。

我真的不习惯使用指针。我做错了什么?

4 个答案:

答案 0 :(得分:2)

有两个问题。首先,你确实对指针/数组感到困惑:

int a[4]; // this is an array of 4 integers, a is the name of the array
int *a[4]; // This is an array of 4 *pointers* to int

所以你的宣言:

int **blah[4];

定义一个指向指针数组的4个指针的数组。也许你对以下事实感到困惑(我知道我是在学习C的时候)。如果您声明变量:

int *a;

这是指向整数的指针的声明。但是如果你有一个变量a是一个指针,你可以通过使用* a来获得它所指向的东西(这里是一个整数):

*a = 1; // a is a pointer (i.e. an address), *a is the value pointed to by a.

因此声明中的*用于声明指针,但* in语句用于表示值。

但是你的第二个问题与指针本身无关。它是关于资源管理(内存是一个,但文件,锁定是其他)。当它超出范围时,在堆栈上分配的任何内容都不再存在。在纯C中,您只有一个解决方案:使用malloc在堆上分配,并确保之后可以释放。所以你会做类似的事情:

// foo is a struct
foo *init_foo()
{
    foo* tmp;
    tmp = malloc(sizeof(*tmp));
    // initialize tmp

    return tmp;
}

然后,你将用另一个功能清理它:

foo *a;
a = init_foo();
// do stuff
clean_foo(a);

示例:FILE *句柄和fopen / fclose(除了分配东西之外,还有一些与操作系统相关的东西来处理文件)。另一个解决方案是使用alloca,它不是标准的C,但是受到许多工具链的支持。

在C ++中,您可以使用智能指针,它使用例如引用计数来进行资源管理。我对C ++不太熟悉,我相信人们会加入这个部分。引用计数的想法是它仍然提供了自动指针的一些优点(你不必自己调用delete,这对于非平凡的项目非常容易出错),但不是纯粹基于范围的。一个基于引用计数的智能指针是boost中的shared_ptr。

答案 1 :(得分:1)

整个概念对我来说很奇怪。如果在堆栈上声明数组,它将不存在于函数范围之外。如果你使用'new'分配它 - 确保你有时'删除'它,否则它是内存泄漏! 带有'new'的正确代码是:

int *blah = new int[4];
...
// don't forget to:
delete [] blah;

答案 2 :(得分:1)

我不确定我是否做对了你想做的事情,但是如果你想要返回一个对randomFunction返回后有效的int数组的引用,一个很好的方法是与Boost:

#include <boost/shared_ptr.hpp>
#include <vector>

boost::shared_ptr<std::vector<int> > randomFunction(int x, int y, int width, int height)
{
  boost::shared_ptr<std::vector<int> > blahPtr(new std::vector<int>(4));
  (*blahPtr)[0] = x;
  (*blahPtr)[1] = y;
  (*blahPtr)[2] = width;
  (*blahPtr)[3] = height;
  return blahPtr;
}

您不必记住delete blahPtr - 当它的所有副本超出范围时,Boost会自动删除您的std::vector对象,以及C ++标准库将删除基础数组。

答案 3 :(得分:0)

看起来你想要一个4x4数组,在这种情况下你应该像这样创建它(从头顶开始的未经测试的代码):

int **blah = new int* [4];
for(int i = 0; i < 4; ++i)
{
    *blah[i] = new int[4];
}

或者,您可以创建一维数组并将其视为二维数组:

int *blah = new int[16];
#define ELEM(x,y) w*4+h
blah[ELEM(1,1)] = 123;