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】


  
const int* a = &b;                 /* [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所指向的内容是不是常量并没有限制。如下面的代码,是可以通过编译的。

 

    const int *p = &b;

    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------*/ 

int a;

const int b;

/*----test1.cc-------*/

#include “A.h”

/*----test2.cc-------*/

#include “A.h” 

 

当test1.cc 和test2.cc 链接的时候,a会出现变量重定义的错误,而b是不会的。因为b是具有内部链接的变量,相当于在test1.cc和test2.cc中各有一份b的符号。

 

const变量放在头文件中是不会引起链接时候的重复定义的,但是也不推 荐将const变量放在头文件中。

const变量不是在编译的时候进行常量折叠,相当于宏的替 换,const变量是不占内存的。

但是 在某一些情况下,编译器会为const分配内存,比如:

 

const int a = 10;

const int *p = &a;

 

当你想获取const变量的地址时(当然你也可以将a的地址打印出来看 看),编译器就会强制为const变量分配内存了。所以当你在含有const变量的头文件被多个编译单元包含时,const变量也有可能在编译单元中占据 内存。所以一般是不推荐将const 或者static变量放在头文件中。当然这样做也无可厚非。

下面这种情况const也是会分配内存的:

 

const int a[5] = {1, 2, 3, 4, 5};

 

所以下面的语句也就自然而然是不能通过编译的了:

 

int arr[a[2]];

 

虽然a[2]的类型也是const int,但是它与下面的这种情况是有区别的:

 

const int k = 3;

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变量分配一个地址。