C/C++中的内存分配问题
先看两个函数:
f(int a);
F(Class1 object1);
在调用时f(b)是值传递,不能改变b的值。而F(object2)可以改变object2的成员变量(至少在java中是这样)。所以我怀疑对象名其实是指针。最近又有朋友和我说其实变量名(包括对象名)对于编译系统来讲,全是指针。
我不知道他说的对不对,不过我想可能对于每一层(stack的每一层)都有一个符号表,记录变量名(包括对象名)和它的内存位置(指针)。所以有了上面的结论。
我的问题是:
有谁知道C/C++的的编译系统的内存分配机制的,特别是关于对象的内存和函数的代码内存方面的?
100分全部送上,或则介绍本书也可以!
问题点数:100、回复次数:13Top
1 楼vampireonline(菜鸟)回复于 2002-11-13 19:09:23 得分 50
虽然说对于编译器来说变量名全部等于内存地址,但是函数传递的过程还是有差别的,如果使用值传递,系统会在被调函数的堆栈里面先创建一个临时的空间用于拷贝实际参数的值到那里,所以值传递的时候你修改的只是那个实际参数的一个副本,而不是它本身,对于对象的值传递也是一样的,它其实是调用了对象的拷贝构造函数来拷贝实参的一个副本给被调函数,你说可以改变它的成员变量,大概是因为你的成员变量里面有指针,而且对指针做了malloc或者是new操作,但是你又没有提供一个自定义的构造函数吧,这样的话确实是有可能改变了你的那个成员变量(可能是一个指针)所指向的那个内存空间的内容吧。JAVA我不知道是不是可以改变,但是C++里面应该如果你的成员变量没有包含指针的话,应该还是不能改变实参的成员变量值的Top
2 楼maskii(小吴)回复于 2002-11-13 19:29:05 得分 0
谢谢上面兄弟vampireonline(菜鸟) 的回答!
只是我更想知道:编译系统是如何分配内存的,从main()开始,到调用函数,而后返回,结束。
而我的问题就是:如果你是一个编译系统的设计者,你会怎么给用户程序分配内存?
至于上面兄弟vampireonline(菜鸟) 说的,可能是java和C++的区别,毕竟,java中是没有指针这种类型了,所以可能对象变量就是指针。我会在C++中试验一下的。Top
3 楼Againstwind(逆风飞扬)回复于 2002-11-13 19:39:19 得分 0
vampireonline(菜鸟) 的回答正解。
至于编译方面的问题,待查!!!Top
4 楼zous(安安)回复于 2002-11-13 19:43:42 得分 50
推荐一本inside C++ object,现在有中译本了,有毅力看看,我没时间看完。类其实是c++提供的一种封装工具(带函数的结构),早期的编译器是把他翻译成c代码编译,xxx class数据类型也就是当成一个指针,你分析时可以把它的成员变量看作一个结构体。用F(Class1 object1)时,函数会生成一个新类,赋值是把两个类的成员相等(依赖于编译器),之后便没有关系,成员变量里面要是有指针,你当然可以用副本里指针找到实参里指针指向的内存,但函数返回时析构就很有可能破坏实参的内存,而且构造和析构都要额外的开销。C++ 里面有引用传值,class& xxx,推荐,是比较安全的做法,但是似乎不能跨越模块,指针最强大,但不安全。Java里的类在虚拟机里是一对指针(sun jvm),一个指向类数据,一个指向他的静态的代码(可能,不记得了),类的析构是由vm的垃圾回收机制自动进行,其实要看虚拟机实现的实现方法。我不是学it的,很久没接触了,错了大家包涵。Top
5 楼zous(安安)回复于 2002-11-13 19:47:58 得分 0
做编译器?这个比较复杂,首先,内存分为Heap,stack,data,text(code).heap是固定内存,比如malloc是从heap分配的,stack 是函数的参数,局部变量,text是代码,data是初试化的变量。Top
6 楼ablist()回复于 2002-11-13 21:08:06 得分 0
UPTop
7 楼abcabcabc___(abcabcabc__)回复于 2002-11-13 21:13:58 得分 0
for f(OBJECTX object)
if you can change object2's value inside f(object2), then it's a bug in compiler.Top
8 楼iicup(双杯献酒)回复于 2002-11-13 21:20:36 得分 0
在 C++中,对象也不会被改变,
看
#include <iostream>
using namespace std;
//定义类
class X
{
public:
int x;
};
//定义函数
void fun(X t)
{
t.x=200;
};
int main(int argc,char* argv[])
{
X a;
a.x=100;
cout<<"old a.x="<<a.x<<endl;
fun(a);
cout<<"new a.x="<<a.x<<endl;
return 0;
}
运行结果:
old a.x=100
new a.x=100
Top
9 楼cwanter(亚玛逊河上的渔夫)回复于 2002-11-15 09:19:37 得分 0
Java不懂,说说C/C++。
C/C++参数传递默认是采用值传递方式。如果你定义函数是传值的话,是不可能改变实参的值。但在参数是大对象的时候,采用传值的效率会很低,应该采用传引用或指针的方式。在参数是大对象的时候,编译器可能采用NRV优化来提高参数传递的效率。
推荐一本书《深度探索C++对象模型》。Top
10 楼zhangxxdd(钱本草:欲教踏春失旧路,相与谁邀?★佛曰:想笑就笑★在我心許多過往的夢 讓每點緊收藏腦中)回复于 2002-11-15 10:03:35 得分 0
我推荐你看 编译原理 :)
传递参数的四种方式 :传值,传地址,引用,传名字!
你不必要买书,可以到vchelp的文档区找 《深度探索》的笔记
作者 雷神 ,呵,很是不错~~
Top
11 楼cwanter(亚玛逊河上的渔夫)回复于 2002-11-15 10:07:00 得分 0
楼上,你是不是W?Top
12 楼lpheni(木鸟)回复于 2002-11-15 12:22:39 得分 0
不管什么都是一样的,你传值进去就不能改,传地址就可以改。Top
13 楼liu_feng_fly(笑看风云 搏击苍穹 衔日月)回复于 2002-11-15 12:41:27 得分 0
java中好象只有内建数据类型是传值调用,对于其他new出来的东西都是传引用调用的吧,在一个函数里面可以改变他。在c++中都是传值调用,一般使用拷贝构造函数,所以和内建的数据类型没有什么区别。
如果对底层实现感兴趣,强烈建议看《深入探索c++对象模型》,我看了3遍,获益非浅Top




