回复 5楼 humy
1.A & 和A *都不是A,即p,qa都不是A类的对象,即使会运用析构函数也不会用A定义的析构函数啊?
是的。
2.这个例子是不是说p,qa,虽然超过作用于不能再被引用,但是他们的空间没被释放?还是说他们的空间也被释放了,只是用的不是析构函数。。。?还是qa这个指针所占内存被释放了,但他所指向的A类对象的内存没释放?
是你说的最后那种情况。指针或者引用的内存都被释放了,但它们指向的对象的内存没有释放。
3.又想了一下,是不是p本身就没有占用内存?他只是a的别名。?所以没析构函数的事?
指针本身也是要占内存的,用 sizeof(p) 之类的语句给出的就是指针本身所要占的内存。但一般无论它指的是什么东西,指针本身占的内存都一样多。32 位的 cpu 一般是 4,64 的是 8 字节。
在观念或者思维上,把它们理解成 a 的别名也行,但 c++ 里没有别名这个概念。
指针是内置类型,和 int 之类的东西一样,一般不需要析构,但也不是不能析构。尤其在模类中,有时有显示调用模版参数的析构函数的必要。如果是析构的内置类型,编译可能只是简单地忽略这个语句。
4.而对于指针,:“对象的引用或指针”和“删除指向动态内存分配对象的指针”中的指针一样吗?如果指针不一样,是取决于他指向的对象的内存的分配方式?比如A* m,n;
A a;
m=&a;
n=new A();则m,n类型不一样,n就是所说的 指向动态内存分配对象的指针 (就是涉及new,delete的) ?
“当对象的引用或指针超出作用于时不会运行析构函数,只有删除指向动态内存分配对象的指针或实际对象而非对象的引用超出作用域时才会运行析构函数。 ”这句话前后的解释是m,n? 于是我把delete pa注释掉,在inner里加了delete qa;
输出。。。所以我又想指针没有不同,要且仅有用了delete就会运行析构。。。不知我的哪个想法是对的?
指针都是一样的,只是指向对象的本质可能不一样。你的例子里,m 和 n 的类型就是一样的。只是 n 指向的是动态分配的对象。
对象的引用是指 A &m = a; 这样的 m 称为 a 的引用。和 A *m = &a,在概念上还是有点区别的。如果是引用的话,一般不用管主体如何,析构主体不是引用的工作。对于指向非动态分配的指针也一样。
而动态的就要自己手动处理。delete 就会运行析构。只要你指针指的地址是曾经 new 分配的就行了,至于是不是一定就是接管收 new 分配的那个指针就无所谓。所以析构 pa 和 qa 都是可以的。但逻辑上不能 delete 两遍,也不能 delete 不是 new 分配的东西。
你的理解基本都是对的。
5.int *p=new int[10];用这个是了一下,成功了。int **p=new int[10];这个就出错了。。我又找了书,在操作符里,new和new【】是分别的两个操作符。。。那他这个p是不是不指数组,只是指int元素?。。。而int **p=new (int*)[10];或(int *)*p=new (int*)[10];也会有一大堆错。。。。
哦,有点明白你的问题了。你是觉得:
int *p = new int(5);
int *q = new int[5];
这两个语句都对很奇怪是吧?其实效果和这个很像:
int a = 5;
int b[5];
int *p = &a;
int *q = &b;
这里 p 指向的就是一个单蹦的元素。后者是一个数组。
而这个例子里第一个就用的是 new 操作符,而第二个是 new[] 操作符。new 操作符可以同时赋个初值,而 new[] 不行。对比直接定义,int a = 5 和 int b[5] = {1, 2, 3, 4, 5 } 都可以赋初值是不太一样的。
这个语句:int **p=new (int*)[10]; 的问题主要是出在 new 运算符的申请对象类型的识别模式对括号比较敏感。
正确的写法是去掉括号,或者变换一下括号的范围: int **p=new int*[10]; 或 int **p=new (int*[10]);
我的这个帖子里:
https://bbs.bccn.net/viewthread.php?tid=364885&page=1#pid2087894
提了 new 加括号的问题,当时我讲的是优先级的问题,但其实不是。只是我当时想的也不是很清楚,所以没敢太仔细地讲。至于你写的那个为什么不对,不深究就是了。它的编译逻辑,我也没有搞清楚。
6.改了一下,把他们放在inner里看是不是只要数组,容器使命结束它就会自动运行析构。。好像是的,结果:。。。
结合版主所说“你自己申请的这 10 个还是得你自己释放。”
我觉得我的这个观点对: 动态分配就是用new什么的,指向他的地址指针什么的不涉及A的析构,这个指针会自己释放的,析构是指释放这些new出来的空间。
对不?
关于指针析不析构的问题,你前面几个问题也有提,就不再重复了。
new 和 delete 的逻辑是这样的,new 会先申请出足够的空间,用来容纳所要求的对象。之后,它就会在这些申请来的空间上执行申请对象的构造函数,如果是数组的话就会执行数次构造出数个对象。构造好了之后,才把这个空间的地址传回去。
delete 的逻辑其实就是 new 的逆。它会先在这些空间上执行一遍或数遍析构函数,先把对象销毁,然后再把销毁后的空间释放回去。
而至于那外指针本身,你写 int *p = new int[5] 其实也能看出来,这个指针本身不是动态分配的,它只是用来接收 new 的返回值而已。等你 delete 掉 p 之后,new 所产生效果就全被抵销了。p 过了生命期,自己自生自灭就无所谓了。不然 p 没以,假如你又没用其它指针指向那个动态分配的空间,就无法用 delete 回收了。这一般称作内存泄露。
关于你最开始问的第一个问题,书里之所以提,是在很多编程语言里,程序员没有管理内存的义务。想要什么对象引用它指向它就是了(其实在这样的语言里,也没有指针的概念,从而也没有指向的说法)。对象和引用是一体的,如果有两个符号引用了同一个对象,那么其中一个引用消失并不会回收对象,只会使它的引用减一。而如果一个对象的引用计数为 0,对会被自动回收。所以你的书提这句话,可能只是想告诉已经习惯这种观念的程序员,小心指针或引用的转移。因为引用的消失,不会再自动触发对象的析构了。