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

Assign temporary struct pointer as 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是一个临时变量,所以引用没有任何意义。我怎样才能正确地做到这一点?

你走在正确的轨道上。在您的第一个示例中,一旦 get_test returns,foo 不再存在,并且访问它所在的地址是未定义的行为。第二次尝试时也会发生同样的情况,但这里的问题出在 get_test 本身。您声明 Foo* foo;,但从未将其分配给任何东西,这意味着变量 foo 指向某个随机地址。访问它是未定义的行为。 试试这个作为你的 get_test-function:

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

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

  return test;
}

在这里,我们用new分配了foo,所以它分配在堆上,并且会一直保留到你在上面调用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 一旦超出范围(当 test 被销毁时)将负责删除 foo,并且您不必担心内存泄漏(但是你不能复制 std::unique_ptr,所以你必须 std::move 它)。 std::unique_ptr 自 c++11 起可用,std::make_unique 自 c++14 起可用。 您还需要 #include <memory> 才能使用它们。 查看此 link to learn more about the difference between heap and stack, and this one 以了解有关 std::unique_ptr 和移动语义的更多信息。