将临时结构指针分配为结构成员

时间:2020-04-01 15:52:57

标签: c++ pointers struct member

假设我具有以下结构:

struct Foo
{
  int val;
};
struct Test
{
  Foo *bar;
};

我想创建一个Test结构:

Test get_test()
{
  Test test;
  Foo foo;
  foo.val = 10;
  test.bar = &foo;

  cout << "INIT: " << test.bar->val << endl;

  return test;
}

int main()
{
    Test test = get_test();
    cout << "AFTER: " << test.bar->val << endl;
    return 0;
}

输出如下:

INIT: 10
AFTER: 32723

我试图以不同的方式做到这一点:

Test get_test()
{
  Test test;
  Foo *foo;
  foo->val = 10;
  test.bar = foo;

  cout << "INIT: " << test.bar->val << endl;

  return test;
}

但这给了我SIGSEGV (Address boundary error)

据我有限的理解,我相信这是因为get_test()中的foo是一个临时变量,因此该引用没有任何意义。如何正确执行此操作?

1 个答案:

答案 0 :(得分:1)

您处在正确的轨道上。在您的第一个示例中,一旦get_test返回,foo就不存在了,访问该地址是未定义的行为。第二次尝试也会发生同样的情况,但是问题出在get_test本身。您声明了Foo* foo;,但从未将其分配给任何内容,这意味着变量foo指向某个随机地址。访问它是未定义的行为。 将此作为您的get_test功能:

Test get_test()
{
  Test test;
  Foo *foo = new Foo();
  foo->val = 10;
  test.bar = foo;

  cout << "INIT: " << test.bar->val << endl;

  return test;
}

在这里,我们用foo分配new,所以它分配在堆上,并且将一直保留到您在其上调用delete为止。这意味着一旦完成,您需要确保delete,否则会出现内存泄漏。在c ++ 14中,您也可以使用std::unique_ptr

struct Test
{
  std::unique_ptr<Foo> bar;
};
{
  Test test;
  std::unique_ptr<Foo> foo = std::make_unique<Foo>();
  foo->val = 10;
  test.bar = std::move(foo);

  cout << "INIT: " << test.bar->val << endl;

  return test;
}

std::unique_ptr将负责删除foo(一旦超出范围(test被销毁)),并且您不必担心内存泄漏(但是您可以无法复制std::unique_ptr,因此您必须std::move)。 std::unique_ptr自c ++ 11起可用,std::make_unique自c ++ 14起可用。 您还需要#include <memory>才能使用它们。 请查看此link,以了解有关堆和堆栈之间区别的更多信息,以及this one,以了解有关std::unique_ptr和移动语义的更多信息。