目录
一.C++的第一个程序
二.命名空间(namespace)
1.命名空间的定义与使用:
(1)命名空间里可以定义变量,函数,结构体等多种类型
(2)命名空间调用(::)与展开
(3)命名空间的嵌套
(4)具体使用场景
三.缺省参数
1.基本定义:
2.几个注意:
四.函数重载
1.定义与使用:
五.引用
1.定义:
2.引用的特性:
3.引用的使用(区别传值返回和传引用返回):
4.const引用:
六.inline内联
一.C++的第一个程序
C++作为C语言的升级版,除了可以无缝兼容C语言的各种语法结构和各种框架外,在很大程度上对C语言的许多代码进行了优化升级,在保持原有代码逻辑结构相同的情况下,C++的简便性和应用性相比C语言不可同日而语,以下我要阐述的就是在学完C语言然后进入C++后需要掌握的一些基础知识:首先来看第一个C++程序
#include<iostream>//C++需要包含的头文件 using namespace std;//展开对应的命名空间 int main() {cout << "hello world" << endl;//区别于C语言的输出方式 //cout<<输出内容,后面的endl是换行(endline),但和C语言里面的\n不用,endl是一个函数。return 0; }
基础结构大概就是这样,下面就是对每一部分的具体介绍:
二.命名空间(namespace)
1.命名空间的定义与使用:
书面上的定义简而言之是:namespace的本质是定义出一个域,这个域跟全局域各自独立,不同的域可以定义同名变量
(1)命名空间里可以定义变量,函数,结构体等多种类型
#include<iostream> namespace space { //定义变量int rand = 10;char time = 20; //定义函数int add(int a, int b){return a + b;} //定义结构体struct student{char name[20];char sex[6];int age;}; } int main() {return 0; }
(2)命名空间调用(::)与展开
在调用的时候,只要用空间名::函数名这样的格式来调用
#include<iostream> int main() {std::cout << "hello world" << std::endl;return 0; }
也可以只展开一个命名空间中的某个变量或函数,这样的话访问这个变量或函数就更简便
#include<iostream> using namespace std; namespace b {int test(int x, int y){return x + y;} } using b::test; int main() {int m = test(1, 5);cout << m;return 0; }
(3)命名空间的嵌套
#include<iostream> using namespace std; namespace a {int test(int x, int y){return x + y;}namespace b{int test(int x, int y){return x * y;}}} int main() {int m = a::test(2, 3);int n = a::b::test(2, 3);cout << m << " " << n;return 0; }
(4)具体使用场景
#include <stdio.h> #include <stdlib.h> int rand = 10; int main() {// 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数” printf("%d\n", rand);return 0; }
这样写c语言会报错:报错的原因就是我们自己定的变量rand和C语言自带的库函数冲突了,这时候编译器就无法识别,这其实是C语言的不足之处。而c++中的命名空间就完美的解决这个问题
三.缺省参数
1.基本定义:
在函数定义时为参数指定的默认值,当调用函数时如果没有传递该参数,则使用默认值。这样可以提高函数的灵活性和可重用性
举例例如一个计算面积的函数,参数有长和宽,其中宽可以设为默认值1,这样调用时只传长就可以得到正方形的面积,这样的例子比较直观#include<iostream> using namespace std; int test(int x = 2, int y = 6) {return x + y; } //如果调用这个函数但是不传递参数,那么返回结果就是8,同样如果掺入参数1和2,那么返回结果就是3
2.几个注意:
(1)缺省参数必须从右往左给,比如上面的程序,我们只给x缺省参数但不给y缺省参数这样其实是不合法的
(2)函数实参一定是从左往右给函数的
(3)函数声明和定义分离时,不能在声明和定义中同时给缺省值
#include<iostream> using namespace std;int test(int x = 1, int y = 2); int main() {int a = test();cout << a;return 0; } int test(int x = 1, int y = 2) {return x + y; } //比如这样同时个给缺省值的函数是不合法的,一般只在声明中给缺省值
四.函数重载
1.定义与使用:
即重名函数可以通过识别传入的参数类型来自动选择相对应的函数,例如:
#include<iostream> using namespace std;int test(int x , int y ) {return x + y; } double test(double x, double y) {return x + y; } int main() {double x = 1.5, y = 2.8;int a = test(1,2);double b = test(x, y);cout << a <<" "<< b ;return 0; }
五.引用
1.定义:
引用不是新定义一个变量,而是给已存在变量取了一个别名,编译器不会为引用变量开辟内存空间,它和它引用的变量共用同一块内存空间,但实际上在C++的底层逻辑里引用依旧是以指针的形式存在,但我们在实际使用中并不需要考虑那么多,就当引用是C++给我们带来的一种更加方便写代码的方法就行了,以下是引用使用的基本规则:
类型& 引用别名=引用对象
#include<iostream> using namespace std; int main() {int a = 30;//一个变量可以取多个别名int& b = a;//给a变量取别名int& c = a;//c也是a的别名int& d = b;//给b变量取别名,相当于d也是a的别名cout << &a << endl << &b << endl << &c << endl << &d << endl;//从地址中也可以看出来a,b,c,d占用同一块内存空间return 0;}
当然,引用相对指针是非常方便好理解的,我举个例子:
#include<iostream> using namespace std; //传址调用,指针 void swap(int* a, int* b) {int tmp = *a;*a = *b;*b = tmp; } //引用 void swap(int& a, int& b)//函数重载 {int tmp = a;a = b;b = tmp; } int main() {int a = 10;int b = 20;swap(a, b);swap(a, b);return 0; }
2.引用的特性:
(1)引用必须在定义时初始化。比如int& a=0;这句代码其实是不合法的
(在 C++ 中,引用必须在定义时初始化,这意味着当声明一个引用变量时,必须立即将其绑定到一个已存在的对象(变量、常量或表达式的结果),与普通变量不同,普通变量可以在后续赋值时初始化)
(2)一个变量可以有多个引用
(3)引用一旦引用一个实体,再不能引用其他实体
举个栗子:
#include<iostream> using namespace std;int main() {int a = 10;int& b = a;int c = 20;b = c;cout << &a <<" "<< &b <<" "<< &c << endl;cout << a <<" "<< b <<" "<< c << endl;return 0; } //这里进行了b=c的操作,只是把c的值赋值给了b,但并没有改变b的引用实体,因此a和b地址是相同的
3.引用的使用(区别传值返回和传引用返回):
引用在实践中主要是于引用传参和引用做返回值中减少拷贝提高效率和改变引用对象时同时改变被 引用对象
引用传参介绍过了,然后我们看一下引用做返回值(即传引用返回)与传值返回区别
int STTop(ST& rs)//注意这里是传值返回(因为返回类型是int二百元引用类型的int&) {assert(rs.top > 0);return rs.a[rs.top]; } int main() {ST st1;STInit(st1);STPush(st1, 1);//入栈STPush(st1, 2);STTop(st1)+=10;return 0; }
截取了一部分之前栈的操作,发现对于STTop(st1)+=10;这个操作无法达到目的,
我们本意想的是让栈顶的数据加上10,但是实际上栈顶的数据并没有改变
这是因为这串代码返回的是一个值,相当于我们把原来的数拷贝出了他的值然后返回了,
因此就算把这份拷贝的值加上10也无法改变原来的栈顶数据
以上发生的情况就是由传值引用引发的,传值引用简而言之就是为了保护源数据不被修改的场景二存在,通过返回对栈顶元素的值的拷贝,从而使实际上的栈顶元素不受改变
但如果代码这样改,就可以轻易改变栈顶元素的值:
(即传引用返回)
int& STTop(ST& rs) {assert(rs.top > 0);return rs.a[rs.top]; } int main() {ST st1;STInit(st1);STPush(st1, 1);STPush(st1, 2);STTop(st1)+=10;return 0; }
4.const引用:
const引用简而言之就是对引用范围的缩小:即 const对象必须用const引用,普通对象也可以用const引用,但普通引用引用不了const对象
#include<iostream> using namespace std; int main() {const int a = 10;//只可读//int& b = a;//发生错误,b可读可写,权限变大//应加上const const int& b = a;int c = 20;const int& d = c;//权限缩小,可以c++;//d++不可以;c可以改变,d不可以return 0; }
这些就涉及到权限的问题,普通对象是一个变量,可以被改变的,所以他的权限更低。而const对象不能被改变所以他的权限更高。普通引用引用const对象权限就放大了,所以编译器会报错,反过来const引用可以引用普通对象,因为权限是可以缩小的,总结来说:访问权限可以缩小,但是不能放大(访问权限只针对引用和指针)
六.inline内联
在 C++ 中,内联函数(Inline Functions)是一种优化机制,旨在通过在编译时将函数体直接替换到调用位置,减少函数调用的开销(如栈帧压入/弹出、参数传递等)
#include<iostream> using namespace std; inline int add(int x,int y) {return x + y; } int main() {cout << add(1, 5) << endl;return 0; }
对于短小的函数,inline操作会使函数在编译时展开,可以提高效率。但是如果这个函数过长就不适合使用内联了,过长的函数内联反而会降低时间,因此,内联函数也并不是万能的
还有一点非常值得注意,就是内联函数的定义和声明必须在同一个文件
欧克了,C++的入门知识大概就是这些了,相比C语言,还是由很多需要管制与在意的地方,那就先这样吧
全文终