从SDL库的函数返回的指针

时间:2019-01-31 05:17:49

标签: c++ memory stack heap-memory

我一直在关注youtube上使用SDL的游戏引擎创建者教程。我已经学习了C ++涉及的许多东西,并且深入研究了指针(原始和智能),并了解了堆栈和堆。在教程中,有一个小函数可以返回一个指针。我不明白的是在整个代码执行过程中该指针如何仍然可用?这是有问题的代码。

SDL_Texture* TextureManager::LoadTexture(const char* texture)
{
  SDL_Surface* tempSurface = IMG_Load(texture);
  SDL_Texture* tex = SDL_CreateTextureFromSurface(Game::renderer, 
      tempSurface);
  SDL_FreeSurface(tempSurface);

  return tex;
}

这段代码包含整个指针信息...

现在,为了学习这种材料,我尝试创建类似的东西来观察内存如何与我创建的函数中的指针一起工作。

int* test() {
  int num = 5;
  return #
}

int main()
{
  int* ptr = nullptr;
  ptr = test();
  std::cout << "Hello World!\n";
  int testArray[5];
  int i = 1;
  testArray[0] = 1;
  testArray[1] = 2;
}

调用int i时,指针信息被破坏。为什么缺少与上面的功能相同的功能,我还缺少什么?

4 个答案:

答案 0 :(得分:1)

test函数中,num是局部变量。它在test()的末尾被销毁。

您需要在test中分配一个整数以使其起作用。在这种情况下,指针的所有权会转让给您:您需要删除它。

int* test() {
  int* num = new int(5);
  return num;
}

int main() {
  int* ptr = test();
  std::unique_ptr<int> int_deleter(ptr);
  std::cout << "Hello World!\n" << *ptr;
}

另一个返回指针的例子是返回一个类成员。在这种情况下,请参阅有关是否转移所有权的文档。例如:

class A {
public:
  A() : num(new int(5)) {}
  virtual ~A () { delete num; }

  // `A` keeps the ownership of the pointer.
  const int* GetNum() const { return num; }

private:
  int* num;
}

int main() {
  A a;
  std::cout << *a.GetNum() << std::endl;
}

回到SDL_CreateTextureFromSurface示例,很可能在该方法中分配了一个新变量。您需要参考documentation关于返回的指针的所有权(无论您是删除库还是删除库)。

答案 1 :(得分:1)

因此,test()中断了this rule right here

不幸的是,我为什么找不到足够的研究来满足我为什么要这样做,但是我会提出怀疑。

num是局部变量。局部变量在堆栈上分配。函数完成执行的那一刻,局部变量(即num)被“弹出”堆栈。也就是说,它们被摧毁了。

通过malloc()new关键字之类分配的变量在堆上分配。 程序

的执行过程中不会破坏堆

在这种情况下,存储在num中的地址:

int *num = new int(37);

是堆上的地址。即使功能完成执行后,它也完全有效。因此,您可以在功能完成后使用它。

答案 2 :(得分:1)

除了其他答案外,SDL是C(不是C ++)API,因此它没有RAII,这意味着不存在自动调用构造函数和析构函数的环境。

您需要调用SDL_DestroyTexture释放纹理。否则,将导致内存泄漏,这与局部变量不同。

您可能会在概念上想到

  • SDL_CreateTextureFromSurface()(或其他纹理生成API)为new SDL_Texture
  • SDL_DestroyTexture(texture)delete texture

答案 3 :(得分:0)

C / C ++中有4种基本存储类:

  1. 自动: 通常在堆栈上创建的本地对象在它们所驻留的作用域到达其末端时会被破坏。作用域通常位于函数主体中,因此,在函数返回时,已经破坏了在函数中构造的所有自动对象。这也包括函数argumemts。
  2. 内部/静态: 它们的寿命比大多数自动变量更长。一旦构建完成,它们将存活到达到程序完成点为止。当它们被自动破坏时。这些对象仅在嵌套模块(翻译单元)/功能/范围中可见/可访问。
  3. 全局/外部: 这些对象的寿命比上述第1 2类中的所有对象的寿命长。当所有自动对象和内部对象都已失效时,它们将在程序启动时构造,并在程序结束之前被销毁。
  4. 动态/堆: 它们具有灵活的使用寿命。它们可以在程序执行期间的任何时间构造,之后也可以随时销毁。他们通常需要手动处理,除非使用适当的智能指针来自动管理其寿命。错误的一种常见来源是无法正确处理它们。

因此通常,将引用/指针返回到任何非自动对象都是可以的。