如果有这么一句程序:vector<string> v1;
v1是分配在栈上吗?不要小看这个问题,书里的基础概念我已经读了几遍,但是这个迷惑仍然不能解决,要不我就不用花时间上网来问了,期望能有高手指教,
按一般的理解,大概是这样:
C++对象存放在堆上还是栈上由你的代码控制,用new申请的对象放到堆上(new是没有重载的),否则放在栈上,比如
class A {};
A a; //A的对象在栈中分配内存
A * a = new A(); //A的对象在堆上分配内存
上面应该是没有疑问的,可是看下面代码:
#include <string>
#include <vector>
using namespace std;
class A {
public:
A(void) :v1(10) {v1[0]="abc";}
vector<string> v1;
};
A *getA()
{
A * a = new A; // 没重载 new 操作符的。
return a;
}
int main()
{
A *b = getA();
string s1("ABCDEFHIMDI");
printf(b->v1[0].data());
if(b->v1.size()==10) printf(":ok");
return 0;
}
按上面逻辑,上面代码中v1应该在栈上,而“a 指向的内存空间(new A)”应该在堆上,当我调用完getA函数之后,函数getA的栈空间会被自动回收,那么获取的对象指针(即b)所指的对象的成员v1就指向无意义的内存空间(已被回收的栈空间)了,按这个逻辑,似乎都是确切无疑的推理,那么程序应该会出问题,可是程序能正常运行输出“abc:ok”,为什么呢?
若解决我的迷惑给72分,我总共才72分,没有耐心或细心读问题的就不要回答了,暂时不需要粗心或太抽象的指导性的意见,谢谢!
v1不一定在堆栈上,在不在堆栈上要看它属于的那个A的实例对象在不在堆栈上。
分配内存只发生在程序的执行过程中,如
int main() { vector<string> v1; }
或
int main() { vector<string>* v1 = new vector<string>(); }
前者v1在栈中分配内存,后者在堆中分配。 也就是说 “非new的对象在栈中分配,new的对象在堆中分配” 这句话是没有问题的。
而你的这个
class A { public: A(void) :v1(10) { v1[0] = "abc"; } vector<string> v1; };
只是一个类的定义,还没有实例化,是不涉及到任何内存分配的,根本不适用于内存分配原则。就算实例化后,v1变量只是a对象的一个成员变量, 它在在堆上还是在栈上是由a对象的分配方式决定的,而不是由其声明方式决定的。 更进一步,分析一下成员变量的内存分布也能发现,v1本身就是和其父对象是同一地址。
A *b = getA(); long offset = (long)(&(b->v1)) - (long)b; //结果是0
也就是说,当A类实例化为a对象的时候,a对象在栈上v1就在栈上,a对象在堆上v1就在堆上。在你的例子里是分配在堆上的,因此是不会随着函数结束被回收的。
你的分析太清晰太贴切了,句句都说中我的迷惑,很感谢你!可惜我先结贴了,因为我从别的地方得知我问题的题目那个命题是否定的,不过你的回答加深了我的理解,得高手不啬指点,今晚收获颇丰,谢谢!