堆栈上声明的类对象是否与其他堆栈变量具有相同的生命周期?
我有这个代码:
#include <stdio.h>
#include <vector>
using std::vector;
#include <string>
using std::string;
class Child;
class Parent
{
public:
Parent(string s) : name(s) { };
vector<Child> children;
string name;
};
class Child
{
public:
Child() { /* I need this for serialization */ };
Child(Parent *p) : parent(p) { };
Parent *parent;
};
Parent
family()
{
Parent p("John Doe");
int i;
printf("family:\n\tparent: 0x%x\n\ti: %x\n", &p, &i);
for (i = 0; i < 2; ++i)
p.children.push_back(Child(&p));
return p;
}
int
main(void)
{
Parent p = family();
printf("main:\n\tparent: 0x%x\n", &p);
for (unsigned int i = 0; i < p.children.size(); ++i)
printf
(
"\t\tchild[%d]: parent: 0x%x parent.name '%s'\n",
i,
p.children[i].parent,
p.children[i].parent->name.c_str()
);
return 0;
}
我的问题:
family
中,是否在堆栈上声明了 Parent p
?从输出来看,它看起来是如此 Child
也会进入堆栈,对吗? Child
实例时,我将一个指向堆栈变量的指针传递给它。我想这是一个 大禁忌 ,因为堆栈变量保证只存在到函数结束。之后堆栈应该被弹出并且变量将被销毁。这样对吗? vector.push_back()
passes arguments by reference ,所以在 family
函数的末尾, p.children
只包含对局部变量的引用,对吗? main
中,为什么我可以访问父级及其每个子级?是不是因为 family
中的局部变量仍然完好无损并且没有被一些后续的函数调用覆盖? 我想我误解了 C++ 中内存中的内容。我真的很想得到一个可以很好地解释它的资源。提前致谢。
编辑
编译源代码并运行的输出:
misha@misha-K42Jr:~/Desktop/stackoverflow$ ./a.out
family:
parent: 0x2aa47470
i: 2aa47438
main:
parent: 0x2aa47470
child[0]: parent: 0x2aa47470 parent.name 'John Doe'
child[1]: parent: 0x2aa47470 parent.name 'John Doe'
最佳答案
由于 Mark Ransom 指出的原因, vector 中的 Child 对象仍然存在,但是每个 Child 包含的指向 Parent * 的指针(指向 p)正如您预期的那样变得无效。
如果它看起来有效,那么可能发生的情况是编译器的优化器内联了 family(),然后组合了 main(){p}
和 family(){p}
的存储以避免复制返回的对象。即使没有内联,这种优化也很可能,但几乎可以肯定。
很容易理解为什么在这种情况下允许它,因为您的 Parent
类没有自定义复制构造函数,但实际上无论如何都允许它。 C++ 标准特别引用 return value optimization ,并允许编译器假装复制构造函数没有副作用,即使它不能证明这一点。
为了解决这个问题,需要在堆上分配 Parent,并且需要做一些其他的准备来释放它。假设不涉及时间旅行(因此没有对象可以成为它自己的祖先),这可以通过使用 tr1::shared_ptr(或 boost::shared_pointer 用于 pre-TR1 编译器)作为每个子级指向其父级的指针来轻松实现。
关于c++ - 在堆栈上创建类对象,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/4894413/