五、专题一经典问题解析

原创 2017年01月03日 00:51:39

问题一、const与引用之间的疑惑

先总结:
1.只有字面量初始化的const常量才会进入符号表(如const int a = 1; 1是字面量)
对const常量取引用(相当于取地址)会导致编译器为其分配空间,但空间里的值不会被使用
使用其他变量初始化的const常量仍然是只读变量(如 int a =4; const b = a; 最后b是只读变量)
2.被volatile修饰的const常量不会进入符号表
退化为只读变量,每次访问都从内存中取值
3.const引用的类型与初始化变量的类型
相同时:使初始化变量成为只读变量
不同时:生成一个新的只读变量,其初始值与初始化变量相同

1.

#include<stdio.h>
int main()
{
    const int x = 1;
    int& rx = const_cast<int &>(x);//一定要注意const_cast 只能用于指针或者引用的转换
    rx = 5;
    printf("%d\n",x);
    printf("%d\n",rx);
    printf("%p\n",&x);
    printf("%p\n",&rx);
    getchar();
    return 0;
}

最后打印x的值为1,rx的值为5,两者的地址都一样
理由:对常量取引用就相当于取地址,都会分配空间,但不会用空间里面的值

2.

#include<stdio.h>
int main()
{
    volatile const int x = 1;//只读变量
    int *p;
    p = const_cast<int *>(&x);//一定要注意const_cast 只能用于指针或者引用的转换
    *p = 5;
    printf("%d\n",x);
    printf("%d\n",*p);
    printf("%p\n",&x);
    printf("%p\n",p);
    getchar();
    return 0;
}

结果打印的值都为5,地址值也一样
理由:被volatile修饰的const常量不会进入符号表,退化为只读变量,每次访问都从内存中取值

3.

#include<stdio.h>
int main()
{
    char c= 'c';
    char& rx = c;
    const int& trx = c;//两边类型不同,变成只读变量
    c = 'a';
    printf("%c\n", c);
    printf("%c\n", rx);
    printf("%c\n", trx);
    getchar();
    return 0;
}

结果c和rx的值都为字符a,这很容易理解,因为只是简单 的引用,但trx的值却为字符c
理由:const引用的类型与初始化变量的类型
相同时:使初始化变量成为只读变量
不同时:生成一个新的只读变量,其初始值与初始化变量相同

问题二、引用与指针的疑惑

1.指针是一个变量,其值为一个内存地址,通过指针可以访问对应内存地址中的值而
引用只是一个变量的新名字,所有对引用的操作(赋值,取地址等)都会传递到其引用的变量上
2.指针可以被const修饰成变量或者只读变量,const引用使其引用的变量具有只读属性
3.指针就是变量,不需要初始化,也可以指向不同的地址,引用必须在定义时初始化,之后无法再引用其他变量

引用的本质就是指针常量?
从c++的角度:
引用与指针常量没有任何关系
引用是变量的新名字,操作引用就是操作对应的变量

从c++编译器的角度来看:
为了支持新概念,“引用”必须要一个有效的解决方案
在编译器内部。使用指针常量来实现“引用”
因此“引用在定义时必须初始化”

答案:在进行c++编程时,直接站在引用的角度看,与指针毫无关系
分析bug时,站在c++编译器角度看

问题三、重载的疑惑

C++编译器对字面量的处理方式
整数型字面量的默认类型为int,占用4个字节
浮点型字面量的默认类型为double,占用8个字节
字符型字面量的默认类型为char,占用1个字节
字符串型字面量的默认类型为const char*,占用4个字节
当使用字面量对变量进行初始化或赋值时
无溢出产生:编译器对字面量进行默认类型转换
产生溢出:编译器会做截断操作,并产生警告

#include <stdio.h>
int main()
{
    printf("sizeof(\'1\') = %d\n", sizeof('1'));
    printf("sizeof(2) = %d\n", sizeof(2));
    printf("sizeof(3.0) = %d\n", sizeof(3.0));

    char c = '1';
    short s = '1';
    int i = '1';
    long l = '1';
    long long ll = '1';

    c = 2;//这里编译器居然没有报错,但如果换成2000时就会发生溢出错误
    s = 2;
    i = 2;
    l = 2;
    ll = 2;

    float f = 0;
    double d = 0;

    f = 3.0;
    d = 3.0;

深入理解重载规则
精确匹配实参
通过默认类型转换匹配实参
通过默认参数匹配实参

三条规则会同时对已存在的重载函数进行挑选
当实参为变量并能够精确匹配形参时,不再进行默认类型转换的尝试。
当实参为字面量时,编译器会同时进行精确匹配和默认类型转换的尝试。

所以以下程序用字面值直接调用时因为有默认类型转换,有些编译器可能不知道应该调用哪个程序从而报错

#include <stdio.h>
void func(int a, int b)
{
    printf("void func(int a, int b)\n");
}
void func(int a, char b)
{
    printf("void func(int a, char b)\n");
}
void func(char a, int b)
{
    printf("void func(char a, int b)\n");
}
void func(char a, char b)
{
    printf("void func(char a, char b)\n");
}
int main()
{
    int a = 1;
    char b = '2';

    func(a, a);
    func(a, b);
    func(b, a);
    func(b, b);

    func(1, 2);
    func(1 '2');
    func('1', 2);
    func('1', '2');

    return 0;
}

问题四、c方式编译的疑惑

#include <stdio.h>
extern "C"
{

    void func(int x)
    {
        const int i = 1;
        int& ri = const_cast<int&>(i);

        ri = 5;

        printf("i = %d\n", i);
        printf("ri = %d\n", ri);
    }
}
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;
}

以上程序用c的方式编译时,代码里边又有c++的语句,居然也能编译通过,原因是

extern “C”告诉编C++译器将其中的代码进行C方式的编译
C方式的编译主要指按照C语言的规则对函数名进行编译
函数名经过编译后可能与源码中的名字有所不同
C++编译器为了支持重载,函数名经过编译后会加上参数信息,因而编译后的函数名与源码中完全不同
C编译器不会在编译后的函数名中加上参数信息
所以方式编译的函数名都一样,而c++的会加上参数的信息
一定注意:
extern “C”中的重载函数经过C方式编译后将得到相同的函数名,因此extern “C”中不允许重载函数,但extern “C”中的函数可以与extern “C”之外的函数进行重载。

5、专题一经典问题解析

1、const和引用的疑惑        #include                int main()        {            const int x = 1;   ...
  • lbd321
  • lbd321
  • 2017年02月21日 21:45
  • 180

专题一之经典问题解析

一.实例1:
  • u014304293
  • u014304293
  • 2014年10月01日 09:11
  • 564

kuangbin专题五 并查集 ZOJ3261 Connections in Galaxy War

题意: 银河系各大星球之间有不同的能量值, 并且他们之间互相有通道连接起来,可以用来传递信息,这样一旦A星球被另一维度的怪物攻击,便可通过通道找到能量值比A星球大的星球来帮忙。但是有一些通道...
  • Start_to_crazy
  • Start_to_crazy
  • 2017年12月17日 22:02
  • 70

c++学习笔记(5.专题一经典问题解析)

本节知识点: 1.const和引用的疑惑:    a.什么是符号表:符号表是编译器在编译过程中产生的关于源程序中语法符号的数据结构,如常量表、变量名表、数组名表、函数名表等等。符号表是编译器自用的内部...
  • qq418674358
  • qq418674358
  • 2013年11月25日 15:20
  • 1273

67-经典问题解析五

1、问题12、 当存在多个函数重载函数时: 编译器优先调用: 1、普通函数的重载 2、函数模板的重载 3、最后在调用可变参数的函数#include #include using names...
  • zy13270867781
  • zy13270867781
  • 2017年11月02日 17:47
  • 96

[kuangbin带你飞]专题五 并查集——题解

[kuangbin带你飞]专题五 并查集——题解
  • hsj970319
  • hsj970319
  • 2017年05月05日 23:16
  • 275

平面点排序(结构体写法)

Ø 题目描述 平面上有n个点,坐标均为整数。请按与坐标原点(0,0)距离的远近将所有点排序输出。可以自己写排序函数,也可以用qsort库函数排序。 Ø 考核知识点 结构体的简单运用。 Ø 解题...
  • Elliot_Alderson
  • Elliot_Alderson
  • 2017年12月03日 14:59
  • 162

第67课 经典问题解析五

1、指针的判别     1.1、拾遗         1.1.1、C++中仍然支持C语言中的可变参数函数         1.1.2、C++编译器的匹配调用优先级:重载函数>函数模板>变参函数 ...
  • qq_35604488
  • qq_35604488
  • 2018年01月30日 19:33
  • 29

1188: 选票统计(一)(结构体专题)

Description 1483. 某单位进行选举,有5位候选人:zhang、wang、zhao、liu、miao。编写程序,统计每人所得的票数。要求每人的信息里包括两部分:name和votes...
  • lvhaoye
  • lvhaoye
  • 2017年08月05日 15:05
  • 339

kuangbin带你飞 专题一 简单搜索 (题解)

POJ 3279  题意:黑白的板,每次选择一个十字形翻转(十字板内黑白互换,若是边界则不管),求最小将原图变为全白的策略。 题解:枚举第一行翻转情况(二进制),2^c,然后验证,由于第一行确定...
  • Miracle_ma
  • Miracle_ma
  • 2015年06月30日 12:28
  • 1214
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:五、专题一经典问题解析
举报原因:
原因补充:

(最多只允许输入30个字)