1、c++ 分配空间
对于全局对象,静态对象以及分配在栈区域内的对象,对它们的内存分配是在编译阶段就完成了,而对于分配在堆区域内的对象,它们的分配是在运行是动态进行的
全局对象和静态对象。编译器会为他们划分一个独立 的段(全局段)为他们分配足够的空间,一般不会涉及到内存空间不够的问题。 ----全局对象和静态对性不会涉及到内存空间不够的问题
栈区域的大小由编译器的设置决定,不管具体的设置怎样,总归它是有一个具体的值,所以栈空间是有限的, ----栈区域会涉及到内存空间不够的问题
对 象的初始化是通过初始化列表来完成,而对象的赋值则才是通过构造函数,或者更准确的说应该是构造函 数的实现体。
---《C++类对象创建过程揭密》delicious c++
2、const 用法:
1. const修饰参数。const只能修饰输入参数。
1)如果输入参数是指针型的,用const修饰可以防止指针所指向的内容被意外修 改。
2)如果参数采用值传递的方式,无需const,因为函数自动产生临时变量复制该参数。
3)非内部数据类型的参数,需要临时对象复制参数,而临时对象的构造,析构,复制较为费时,因此建议采用前加const的引用方式传递非内部数据类型。而 内部数据类型无需引用传递。
2. const修饰函数返回值。
1)函数返回const指针,表示该指针不能被改动,只能把该指针赋给const修饰的同类型指针变量。
2)函数返回值为值传递,函数会把返回值赋给外部临时变量,用const无意义!不管是内部还是非内部数据类型。
3)函数采用引用方式返回的场合不多,只出现在类的赋值函数中,目的是为了实现链式表达。
3. const+成员函数。任何不修改数据成员的函数都应该声明为const类型,如果const成员函数修改了数据成员或者调用了其他函数修改数据成员,编 译器都将报错!
几个误区:
【误区1】
int const *a = &b; /* [2]*/
int* const a = &b; /* [3]*/
const int* const a = &b; /* [4]*/
看看上面的4行代码,或许可以这么理解:
如果const位于星号的左侧,则const就是用来修饰指针所指向的变 量,即指针指向为常量;如果const位于星号的右侧,const就是修饰指针本身,即指针本身是常量。因此,[1]和[2]的情况相同,都是指针所指向 的内容为常量(const放在变量声明符的位置无关),这种情况下不允许对内容进行更改操作,如不能*a = 3 ;[3]为指针本身是常量,而指针所指向的内容不是常量,这种情况下不能对指针本身进行更改操作,如a++是错误的;[4]为指针本身和指向的内容均为常 量。
但是我想上面的解释不一定正确. 关于const int* a = &b, 并不是说a所指向的是常量,而应该理解成: a所指向的内容不能通过*a来改变,对于a所指向的内容是不是常量并没有限制。如下面的代码,是可以通过编译的。
int *q = &b;
*q++;
【误区2】C++中的const 是具有内部链接的( 不同于C)
下面是摘自C++中关于链接的一段话:
— When a name has external linkage, the entity it denotes can be referred to by names from scopes
other translation units or from other scopes of the same translation unit.
— When a name has internal linkage, the entity it denotes can be referred to by names from other scope
the same translation unit.
— When a name has no linkage, the entity it denotes cannot be referred to by names from other scopes.
A name having namespace scope (3.3.5) has internal linkage if it is the name of
— an object, reference, function or function template that is explicitly declared static or,
— an object or reference that is explicitly declared const and neither explicitly declared extern nor
previously declared to have external linkage; or
— a data member of an anonymous union.
从上面可以看出const对象是具有内部链接的。
内部链接的意思就是:
/*----A.h------*/
const int b;
/*----test1.cc-------*/
/*----test2.cc-------*/
当test1.cc 和test2.cc 链接的时候,a会出现变量重定义的错误,而b是不会的。因为b是具有内部链接的变量,相当于在test1.cc和test2.cc中各有一份b的符号。
const变量放在头文件中是不会引起链接时候的重复定义的,但是也不推 荐将const变量放在头文件中。
const变量不是在编译的时候进行常量折叠,相当于宏的替 换,const变量是不占内存的。
但是 在某一些情况下,编译器会为const分配内存,比如:
const int *p = &a;
当你想获取const变量的地址时(当然你也可以将a的地址打印出来看 看),编译器就会强制为const变量分配内存了。所以当你在含有const变量的头文件被多个编译单元包含时,const变量也有可能在编译单元中占据 内存。所以一般是不推荐将const 或者static变量放在头文件中。当然这样做也无可厚非。
下面这种情况const也是会分配内存的:
所以下面的语句也就自然而然是不能通过编译的了:
虽然a[2]的类型也是const int,但是它与下面的这种情况是有区别的:
int arr[k];
因为k是const 类型,在编译的时候进行了常量折叠。而上面的a[2]虽然也是const int型,但是它存在于内存中。数组声明时数组的维数是不允许用内存中的数据来定义的。所以编译器会在此报出illegal的错误。
当然可能不同的编译器会有不同的编译结果。比如在gcc下你编译上述的代 码会诡异的通过,但是这是不符合C++标准的。当然如果你加上参数-pedantic的话,你就会发现编译器乖乖的听你的话了。
const变量在大部分情况下是编译时的常量,如果需要运行时的常量,应 该怎么做呢?像下面的代码这样:
const int const_runtime = get_v() // get_v在其他地方定义
------ http://www.cppblog.com/xlyz/archive/2010/06/06/117256.html
const 总结:
一般情况下,编译器是不对const变量进行内存分配的,会直接进行常量折叠,类似于宏定义。 而如果你要想取得const类型变量的地址的话,那编译器就会为const变量分配一个地址。
转载于:https://blog.51cto.com/neuloner/330973