C++中需要注意的细节你知道吗

时间:2021-09-23 22:37:12

namespace的使用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#include <iostream>
using namespace std;
//定义命名空间
namespace NameSpaceA
{
    int a = 0;
}
namespace NameSpaceB
{
    int a=1;
    namespace NameSpaceC
    {
        struct Teacher
        {
            /* data */
            char name[10];
            int age;
        };
    }
}
int main()
{
    //using namespace NameSpaceA;
    using NameSpaceB::NameSpaceC::Teacher;
    using namespace NameSpaceB;
    printf("a = %d \n",a);
    printf("a = %d \n",NameSpaceA::a);
    Teacher t1;
    t1.age = 20;
    printf("age: %d \n",t1.age);
    return 0;
}

const使用:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
//C++编译器对const常量的处理
//当看见常量声明时,会在符号表中放入常量-->当要使用时,直接取符号表中的值替换
//C中的const变量是个只读变量,但自己的存储空间
//C++中-->const为全局或&时才会分配空间
//#define和const相同之处:C++中的const修饰,是一个真正的常量,而C中只是个只读变量。const修饰的常量在编译期间就确定了。
//#define与const不同之处:#define-->由预处理器处理,单纯的文本替换
//                       const---->编译器处理,提供类型检查和作用域检查
#include <iostream>
using namespace std;
void fun1()
{
    #define a 10
    const int b = 20;
}
void fun2()
{
    printf("%d\n",a);
    //cout<<b<<endl;
}
int main()
{
    //int &a = 20;
    const int &b = 30;   //直接取符号表中的值代替,当使用&或者extern时会给常量分配内存空间
    fun1();
    fun2();
    getchar();
    return 0;
}

引用

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
//引用的本质:
//          1 引用在C++内部实现是一个常指针   Type &name --> Type * const name
//          2 C++编译器在编译过程中使用常指针作为引用的内部实现.因此所占用的空间与指针一样大 4
//          3 C++为引用的使用做了细节隐藏
/*
    函数返回值是引用:
           1  难点注意:要观察返回的变量是在哪里分配内存空间的--->如果是临时变量,即在栈上分配内存,函数返回时会被析构(释放)
                            --> 不能作为左值使用,因为空间被释放了。没地方存了
                            --> 不能成为其它引用的初始值,空间被释放了
           2  c++链式编程编程、操作符重载
*/
/*
    指针的引用-->只不过是为存储指针的这块内存取了个别名而已
*/
#include <iostream>
using namespace std;
//证明引用有自己的内存空间
struct  Teacher
{
    /* data */
    int &a;
    int &b;
};
int main2()
{
    printf("sizeof(Teacher):%d \n",sizeof(Teacher));  //8-->int const *a and int const *b
    return 0;
}
int main1()
{
    int a   =  10;
    int &b  = a;
    printf("&a:%d\n",&a);
    printf("&b:%d\n",&b); 
    //对同一内存空间可以取好几个名字吗?    -->   不行
    //实际上:int const *b = &a     &b:编译器会帮我们做 *(&b)
    return 0;
}
//引用做函数返回值
int f1()
{
    int a;
    a = 10;
    return a;
}
int &f2()
{
    int a;
    a = 20;
    return a;
}
int *f3()
{
    int a;
    a = 30;
    return &a;
}
//---> 害,其实就一句话,看内存有没有被释放而已
//static + &引用
int j()             //-->返回的只是一个数值而已
{
    static int a = 10;
    a++;
    printf("a:%d \n",a);
    return a;
}
int &j2()           //返回 *(&a)
{
    static int a = 20;
    a++;
    printf("a:%d \n",a);
    return a;
}
int *j3()           //->返回的是一个地址
{
    static int a = 30;
    a++;
    printf("a:%d \n",a);
    return &a;
}
int main33()
{
    //j()-->返回的是一个数值,不能当左值  11 = 100(err)
    j2() = 100;
    j2();
    //手工打造引用条件
    *(j3()) = 100;
    j3();
    getchar();
    return 0;
}
//非基础类型:可能设计到深拷贝和浅拷贝的问题-->其实也就是有没有内存空间的问题
struct Student
{
    int  age;
};
Student & Op(Student &s)
{
    /* data */
    s.age = 30;
}
int main44()
{
    Student s1;
    s1.age = 20;
    Op(s1);
    cout<<s1.age;
    return 0;
}
//常引用-->const难点
int main55()
{
    int a = 10;
    const int &b = a;   //const char const* b = xxxx ---> 但a可以改变
   // b = 11;  
    a = 20;
    int *p = (int *)&b;
    //
    const int aa = 20;
    const int &bb = aa;
    //int &b = aa;
}
//const:常量 pk 变量 -->const int *const  p
int main()
{
    const int b =10;
    printf("&b:%d \n",&b);
    const int &bb = 19;
    printf("&bb:%d \n",&bb);
    getchar();
    return 0;
}

三目运算

?
1
2
3
4
5
6
7
8
9
10
11
12
//在C++中,三目运算返回变量本身,可以做左值
#include <iostream>
using namespace std;
int main()
{
    int a = 20;
    int b = 30;
    a = (a<b?a:b) = 30;
    cout<<a<<endl;
    getchar();
    return 0;
}

函数相关

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
#include <iostream>
using namespace std;
/*
    第一部分:inline函数
        1.内联函数声明时inline关键字必须和函数定义结合在一起,否则编译器会直接忽略请求
        2.内联函数是一种特殊的函数,具有普通函数的特征(参数检查,返回类型等)
            -->相对于普通的函数而言,内联函数省去了压栈、跳转、返回的开销
        3.内联函数由编译器处理,然后将编译后的函数体直接插入调用的地方
          宏定义-->预处理器处理,进行简单的文本替换,没有任何编译过程
*/
#define  MYFUNC(a,b)    ((a)<(b)?(a):(b))   //预处理阶段,简单的文本替换
inline int func(int a , int b)      //经历编译过程
{
    return a<b?a:b;
}
int main01()
{
    int a = 1;
    int b = 3;
    int c =func(++a,b);
    cout<<c;    //2
    int d = MYFUNC(++a,b);
    cout<<d<<"  "//3
    getchar();
    return 0;
}
/*
    第二部分:函数的占位参数:
            占位参数只有参数类型声明,而没有参数名声明
            一般情况下,函数内部无法使用占位参数
*/
int f(int a , int b , int)
{
    return a+b;
}
int main02()
{
    // int c = f(1,2);
    //cout<<c<<"  ";
    int d = f(1,2,3);
    cout<<d;
    getchar();
    return 0;
}
//默认参数和占位参数一起使用-->可以方便程序的扩展
int f2(int a,int b,int = 0)
{
    return a+b;
}
int main022()
{
    f2(1,2);
    f2(1,2,3);
    getchar();
    return 0;
}
/*
    第三部分:
        函数重载-->参数个数不同 、 参数类型不同 、 参数顺序不同
        编译器调用重载函数的准则:
                将所有同名函数作为候选者
                尝试寻找可行的候选者
                精确匹配实参
        匹配失败:
                找到的可行函数不唯一,出现二义性,编译失败
                没有找到可行的函数
        注意事项:
                重载函数在本质上是不同的函数,是相互独立的(静态链编)
                函数重载是发生在同一个类里面的
*/
//函数重载遇上函数指针
int g(int x)
{
    return x;
}
int g(int a ,int b)
{
    return a+b;
}
typedef int(*PFUNC)(int);
int main()
{
    int c = 0;
    PFUNC p = g;
    c = p(1);
    cout<<c<<endl;
    getchar();
    return 0;
}
//register-->暗示编译程序相应的变量将被频繁的使用,如果可能的话,应该将其放到CPU的寄存器中,加快访问速度
//减少了去内存中寻址、取值
// #ifdef NOSTRUTASSIGN
//     memcpy (d , s , l)
//     {
//         register char *d;
//         register char *s;
//         register int  l;
//         while (l--)
//         {
//             *d++ = *s++;
//         }
//     }
// #endif

总结

本篇文章就到这里了,希望能够给你带来帮助,也希望您能够多多关注服务器之家的更多内容!

原文链接:https://blog.csdn.net/weixin_46120107/article/details/120355374