c++经典问题解析 一(6)

------/const和引用
    volatile const int y = 2; //volatile导致y蜕化为只读变量,未进入符号表 
    int* p = const_cast<int*>(&y);
    *p = 6;
    printf("y = %d\n", y); //6 
    printf("*p = %d\n", *p); //6
符号表是编译器在编译过程中产生的自己用的内部数据结构,如常量表、变量名表、数组名表、函数名表等,不会进入最终可执行文件
只有用字面量初始化的const常量才会进入符号表,如const int i=0;
对const常量取引用导致编译器为其分配空间,虽被分配空间,但其值不会被使用
用其它变量初始化的const常量仍然是只读变量
被volatile修饰的const常量不会进入符号表,退化为只读变量,每次访问都从内存取值
const引用类型与初始化变量类型相同,则使初始化变量成为只读变量,不同则生成一新的只读变量,其初始值与初始化变量相同
编译期间不能直接确定初始值的const量,都被作为只读变量处理
------/指针和引用
struct SV
{
    int x;
    int y;
    int z;
};
struct SR
{
    int& x;
    int& y;
    int& z;
};
int main()
{
    SV sv = {1, 2, 3};
    SR sr = {sv.x, sv.y, sv.z};
    
    printf("&sv = %p\n", &sv);
    printf("&sv.x = %p,&sv.y = %p,&sv.z = %p\n", &sv.x,&sv.y,&sv.z);
    
    printf("&sr = %p\n", &sr);
    printf("&sr.x = %p,&sr.y = %p,&sr.z = %p\n", &sr.x,&sr.y,&sr.z);
    
    SV& rsv = sv;
    rsv.x = 4;
    rsv.y = 5;
    rsv.z = 6;
    printf("sv.x = %d,sv.y = %d,sv.z = %d\n", sv.x,sv.y,sv.z);
    return 0;
}


区别:指针是一变量,其值为一内存地址,通过指针可以访问对应内存的值;引用是一变量的新名,所有对引用的操作(赋值,取地址等)都会传递到其引用的变量上;指针可被const修饰为常量或只读变量,const引用使其引用的变量具只读属性;指针就是变量,不需初始化,也可指向不同的地址,引用天生就必须在定义时初始化,之后无法再引用其它变量
------/引用本质是指针常量
从C++角度看,引用与指针常量没任何关系,引用是变量新名字,操作引用即操作对应变量
从C++编译器角度看,为支持新概念"引用"必须要有一个解决方案,在编译器内部,使用指针常量来实现引用,因此引用在定义时必须初始化
进行C++编程时,直接站在使用角度看待引用,与指针毫无关系
当对C++程序中涉及引用的bug或奇怪行为进行分析时,可站在编译器角度看待引用
------/重载
    printf("sizeof('1') = %d\n", sizeof('1'));
    printf("sizeof(2) = %d\n", sizeof(2));
    printf("sizeof(3.0) = %d\n", sizeof(3.0)); //148,默认char、int、double
C++编译器对字面量的处理:
整数型字面量默认类型int,占4字节
浮点型字面量默认类型double,占8字节
字符型字面量默认类型char,占1字节
字符串型字面量默认类型const char*,占4字节
当使用字面量对变量进行初始化或赋值时
无溢出产生:编译器对字面量进行默认类型转换
产生溢出:编译器会做截断操作,并产生警告
void func(int a, int b)
{
}
void func(int a, char b)
{
}
func(1, 2);
char b=2无溢出,不产生警告,该规则导致某些c++编译器无法找到func(1,2)所对应的重载函数
深入理解重载规则:
精确匹配、通过默认类型转换匹配、通过默认参数匹配
三条规则同时对存在的重载函数进行挑选:
当实参为变量且能够精确匹配形参时,不再进行默认类型转换
当实参为字面量,编译器会同时进行精确匹配和默认类型转换的尝试
------/extern
extern "C"

    void func(int x)
    {
        const int i = 1;
        int& ri = const_cast<int&>(i);
        ri = 5;
        printf("i = %d\n", i); //1
        printf("ri = %d\n", ri); //5
    } //按照c方式编译,为何还认得const_cast、还是真正意义的常量?
}
void func(const char* s)
{
    printf("%s\n", s);
}
int func(int a, int b)
{
    return a + b;
}
int main()
{
    func(1);
    func("Delphi Tang");
    func(1, 2); 
    return 0;
}
extern "C"告诉C++编译器将其中代码进行C方式编译
C方式编译主要指按照C语言规则对函数名进行编译(函数体仍为c++编译),函数名经过编译后可能与源码中名字有所不同,C++编译器为支持重载,函数名经过编译后会加上参数信息,因而编译后的函数名与源码中完全不同,C编译器不会在编译后的函数名加参数信息
extern "C"中重载函数经C方式编译后得到相同函数名,故extern "C"中不允许重载函数,但extern "C"中函数可与extern "C"之外函数进行重载

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值