【问题标题】:C++: how do I create an object in stack memory that points to the object I am generating it from?C++:如何在堆栈内存中创建一个指向我从中生成它的对象的对象?
【发布时间】:2013-04-12 05:42:13
【问题描述】:

我有一个带有构造函数 Foo(Bar * b) 的类 Foo。我想要类 Bar 中的一个函数,它返回一个指向该 Bar 的 Foo。我试试:

Foo& Bar::make_foo() {
  Foo f((Bar*)this);
  return f;
}

但是 G++ 告诉我:

error: variable ‘Foo f’ has initializer but incomplete type

现在我知道这在堆内存中可以正常工作:

Foo* Bar::make_foo() {
  Foo * f = new Foo((Bar*)this);
  return f;
}

编辑:显然问题是由于类定义不完整。但是我仍然很好奇是否有适当的习惯用法来返回堆栈内存中的对象。

【问题讨论】:

  • 动态分配真的很好用吗?你试过了吗?尽管如此,您的堆栈版本会有问题。 f 对象将在 make_foo 结束时被销毁,返回的引用将悬空。
  • 您的Foo 声明是什么样的?
  • 是的,这就是我所意识到的。是否有在堆栈内存中执行此操作的习惯用法,还是我不应该打扰?
  • @DavidPfau:对于自动持续时间对象(通常被错误地称为“堆栈”对象),规范是返回对象。一旦函数返回,引用或指针将无效。 C++ 通常(但不总是)会忽略临时对象构造和副本,而只是直接修改您分配结果的对象。 C++11 将允许您指定移动构造函数和移动赋值运算符,用于复制由于某种原因可以或不应该工作的情况......但实际上,除非您绝对需要,否则通常不值得。只需返回实际对象。

标签: c++ pointers


【解决方案1】:

无论如何,这段代码都是错误的,因为它返回堆栈上的一个对象,这意味着一旦您从函数返回,该空间可用于存储其他对象 - 这根本不会结束。

Foo& Bar::make_foo() {
  Foo f((Bar*)this);
  return f;
}

只要Bar 被声明为应有的状态,您就应该能够做到这一点——除了担心“您正在使用将被释放的堆栈空间”。

【讨论】:

  • 多么奇怪的答案。 “你应该能够做到这一点——除了它不起作用的事实。” :-)
  • 我的意思是,如果您只需要在函数内部使用f,并且正确声明了 Bar,它就会起作用。返回一个局部变量的局部引用显然仍然是错误的。
【解决方案2】:

以下对我有用 (http://codepad.org/feWQYjtt)。注意:我对make-foo的签名稍作改动,返回本地对象的引用没有意义。

struct Bar;
struct Foo {
    Foo( Bar * ) {}
};

struct Bar {
    Foo make_foo() {     // Signature changed
        return Foo( this );
    }
};

int main() {
    Bar barObj;
    Foo fooObj = barObj.make_foo();
    (void) fooObj;
}

【讨论】:

  • foo 被复制了多少次?答案留给读者作为练习。
  • 有趣的评论:-),返回值优化怎么样?请参阅 cHao 的评论(在问题中)。
  • C++11 确实混淆了这一点,但即使对于旧版本的 C++,您所要做的就是添加在 make_foo 中返回两个 Foo 之一的可能性,并且 RVO 不再起作用。
  • 或许,return Foo( this );,即返回一个未命名的对象会更好?
猜你喜欢
  • 2017-12-06
  • 2014-11-12
  • 1970-01-01
  • 2020-07-26
  • 1970-01-01
  • 2012-02-05
  • 2014-07-04
  • 1970-01-01
  • 2015-03-13
相关资源
最近更新 更多