❀一文入门,一发入魂
# 1. 命名空间namespace
#include <stdio.h>
//在main函数外定义的空间,里面的变量为全局变量 ——静态区
//命名空间可以包含变量,函数声明,结构体等。
namespace myspace //定义了一个自己命名空间,防止命名冲突
{
int a = 0; //变量可以被初始化,但不允许再赋值
namespace childspace
{
int a = 10;
}
}
namespace myspace //相同名字的命名空间会被合并
{
int b = 100;
}
using myspace::b; //指定展开某个变量;一般为常用的
using namespace myspace; //将命名空间展开到全局,这样再访问空间中的名字不必再::(域作用限定符)指定
int main()
{
int a = 20;
printf("%d\n", a);
printf("%d\n", myspace::a); //:: 域作用限定符
printf("%d\n", myspace::childspace::a);
printf("%d\n", b);
return 0;
}
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
# 2. 标准输入输出流
#include <iostream>
using std::cout;
using std::cin;
int main()
{
int a = 6;
double b = 3.14;
// c++兼容c,若用printf方便,则可以使用printf进行输出
cout << "Hello World!";
cout << '\n';
cout << a << '\n'; // cout 支持不同类型数据的输出
cout << b << '\n';
cin >> a >> b;
cout << b << a;
return 0;
}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 3. 缺省参数
函数值缺省参数,半缺省——必须从右向左缺省,必须连续;因为C++在传参时,函数值是从左向右进行赋值的,并且不支持中间赋值。
在头文件和源文件中定义的函数,不能同时设置缺省参数——推荐将缺省参数值写在声明(头文件)中
缺省对于对象而言,不用传入任何参数可以调用缺省值的,就是全缺省。
# 4. 函数重载
C++支持对同名函数的定义,但需保证函数有一定区别,使得编译器对不同的函数生成不同的修饰名(C和C++对于函数的修饰规则不同)。在函数调用时会根据传入传出的参数类型进行相应函数的调用。
同名函数的定义需要体现的不同:
函数类型不同(只有返回值类型不同不构成重载)
函数中的参数不同(包括参数的类型、个数、参数的顺序不同),只参数名字不同或者是否缺省参数不能构成重载
//对于以下函数,可以重载但是调用存在歧义
void fun()
{
printf("fun1\n");
}
void fun(int a = 0) //若只定义int a;仍然可以调用成功
//函数缺省参数,调用时可以不带参数,fun();但若未给值,则必须带参数
{
printf("fun2\n");
}
2
3
4
5
6
7
8
9
10

# 5. 引用
没有开辟新的空间,只是对原来的空间取了一个别名。

需要注意:
- 引用在定义时必须初始化,必须指定给哪个变量指定别名
- 一个变量可以有多个引用(多个名字),但一个引用只能引用一个变量(且不能改变,由初始化规定了)

函数传值和函数传引用构成重载,但是调用存在歧义
void Print(int a) { printf("%d\n", a); } void Print(int& a) { printf("%d\n", a); }
1
2
3
4
5
6
7
8
9引用作函数返回值时,要注意函数内部创建的变量若被销毁,传引用会造成非法访问;传引用返回可以用于静态变量和malloc变量,其作用为:
- 提高运行效率,如大的结构体,不用再将返回值先拷贝到一个大的空间。
- 传引用返回的变量,其空间的内容可以被修改。若用传参数返回,返回的参数实际是一个临时的空间,是对原空间的拷贝;临时变量具有常性,不能被修改,只能给其他变量赋值(是右值)。
引用的权限
引用只能对变量的权限进行缩小或不变引用,不能放大原变量的权限。
const int a; int& b = a; // a只能读不能写,而b可读可写;b对a的权限进行了放大,是不行的
1
2变量的整形提升,如由
char->int
,不是在原空间进行修改,会将char
先拷贝到一个int
大小的临时空间(临时变量),然后进行修改。如上所诉,临时变量具有常性:char a = 'A'; int& b = a; //不行 const int& b = a; //可以
1
2
3函数的表达式也具有上诉临时变量的特性:
int a = 6; int b = 6; const int& c = a + b;
1
2
3
# 6. extern “C”
为了保证C++可以调用C的库,需要在C++的头文件中,将C的库的头文件用extern “C”包含:
extern "C" { #include "_XClib.h" }
1
2
3
4
这样C++编译器会根据C的修饰规则对C库中的函数名进行#include "_XClib.h"
为了保证C可以调用C++的库,则需要在C++的库头文件中将要被C调用的函数用extern “C”包含:
extern "C" { void FunctionInCpplib(); }
1
2
3
4这样编译器会根据C的修饰规则对C++的函数名进行修饰。此时被包含的函数中不允许重载等Cpp的特性。但是要注意以上头文件中extern “C” 无法被C程序识别,C程序直接包含该头文件会报错,需要改写如下:
#ifdef __cplusplus extern "C" { #endif void FunctionInCpplib(); #ifdef __cplusplus } #endif
1
2
3
4
5
6
7
8
9
# 7. 内联函数inline
C++在普通函数前加inline
构成内联函数;该函数在release版本下会将函数直接展开,而不建立栈帧,从而优化性能。而在debug版本下仍然是建立栈帧,从而实现对函数的调试。
当函数很长或者是递归函数时,编译器会忽略内联;内联函数的声明和定义不能分离,因为内联函数没有地址,链接时找不到,所以应直接在定义时就加inline
,写在头文件中。
C++不推荐用宏,推荐用const、枚举、内联来替换。
# 8. auto
auto可以根据赋值变量的类型去推导定义新变量
int a = 6;
auto b = a;// b被自解为int
typeid(a).name();
const int x;
const auto y = x; //不加const,自动推导的类型为int
auto a = &x;
auto* a = &x; // 两个a都是 int*类型
2
3
4
5
6
7
8
9
- auto不能声明函数形式参数的类型,也不能声明数组。
- 范围for
int arr[] = {1, 2, 3, 4};
for(auto e: arr) //取数组里的值赋给e,e相当于临时变量;改变e不改变arr -> 可以auto &e
{
cout<< e << endl;
}
2
3
4
5
# 9. nullptr
空指针推荐使用nullptr,而不使用NULL。因为null被宏定义为0,编译时会被替换成‘0’,这会使得函数重载发生歧义。