目录
1.C++的第一个程序
C++兼容C语⾔绝⼤多数的语法,所以C语⾔实现的hello world依旧可以运⾏,C++中需要把定义⽂件代码后缀改为.cpp
C++版本的hello world:
#include<iostream>
using namespace std;
int main()
{
cout << "hello world" << endl;//打印 hello world
return 0;
}
2.命名空间
将变量、函数和类的名称全都存在于全局作用域中,可能会导致很多冲突。使用命名空间的目的是对标识符的名称进行本地化,以此避免命名冲突或名字污染。
#include<stdio.h>
#include<stdlib.h>
int rand = 10;
int main()
{
// 编译报错:error C2365 :"rand":重定义;以前的定义是"函数"
printf("%d\n",rand);
return 0;
}
2.1namespace
· 定义命名空间,需要使⽤到namespace关键字,后⾯跟命名空间的名字,然后接⼀对{}即可,{} 中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。
· namespace本质是定义出⼀个域,这个域跟全局域各⾃独⽴,不同的域可以定义同名变量,所以 下⾯的rand不在冲突了。
· namespace只能定义在全局,也可以嵌套定义。
· 项目中多⽂件中定义的同名namespace会认为是⼀个namespace,不会冲突。
· C++标准库都放在⼀个叫std(standard)的命名空间中。
#include<iostream>
namespace shen
{
//命名空间中可以定义变量/函数/类型
int rand = 20;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
int main()
{
printf("%d\n",shen::rand);//指定shen命名空间中的rand
return 0;
}
2.2命名空间的嵌套
namespace shen
{
namespace jie
{
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
}
namespace yu
{
int rand = 20;
int Add(int left, int right)
{
return (left + right) * 10;
}
}
}
int main()
{
printf("%d\n",shen::jie::rand);//10
printf("%d\n",shen::yu::rand);//20
printf("%d\n",shen::jie::Add(10,20));//30
printf("%d\n",shen::yu::Add(10,20));//300
return 0;
}
2.3多文件定义同名namespace默认合并
2.3.1Stack.h
#pragma once
#include<iostream>
#include<assert.h>
namespace shen
{
typedef int STDatatype;
typedef struct Stack
{
STDatatype* a;
int top;
int capacity;
}ST;
void STInit(ST* ps, int n);//栈初始化
void STPush(ST* ps,STDatatype x);//栈插入
}
2.3.2Stack.cpp
#include"Stack.h"
namespace shen
{
void STInit(ST* ps, int n)
{
assert(ps);
ps->a = (STDatatype*)malloc(n * sizeof(STDatatype));
ps->top = 0;
ps->capacity = n;
}
void STPush(ST* ps, STDatatype x)
{
assert(ps);
if(ps->top == ps->capacity)
{
printf("扩容\n");
int newCapacity = ps->capacity == 0 ? 4 : ps->capacity * 2;
STDatatype* tmp = (STDatatype*)realloc(ps->a, newcapcity * sizeof(STDatatype));
if(tmp == NULL)
{
perror("realloc fail");
return;
}
ps->a[ps->top] = x;
ps->top++;
}
}
2.3.3test.cpp
#include"Stack.h"
int main()
{
shen::ST st;
shen::STInit(&st);
shen::STPush(&st, 1);
shen::STPush(&st, 2);
return 0;
}
2.4使用
编译查找⼀个变量的声明/定义时,默认只会在局部或者全局查找,不会到命名空间⾥⾯去查找。所以 下⾯程序会编译报错。所以我们要使⽤命名空间中定义的变量/函数,有三种⽅式:
· 指定命名空间访问,项⽬中推荐这种⽅式。
· using将命名空间中某个成员展开,项⽬中经常访问的不存在冲突的成员推荐这种⽅式。
· 展开命名空间中全部成员,项⽬不推荐,冲突⻛险很⼤,⽇常⼩练习程序为了⽅便推荐使⽤。
#include<iostream>
namespace shen
{
int a = 20;
int b = 10;
}
编译报错
int main()
{
printf("%d\n",a);//未定义的标识符a
return 0;
}
指定命名空间访问
int main()
{
printf("%d\n",shen::a);
return 0;
}
using将命名空间中某个成员展开
using shen::a;
int main()
{
printf("%d\n",a);
return 0;
}
展开命名空间中全部成员
using namespace shen
int main()
{
printf("%d\n",a);
printf("%d\n",b);
return 0;
}
3.C++输入&输出
· <iostream> 是 Input Output Stream 的缩写,是标准的输⼊、输出流库,定义了标准的输⼊、输 出对象。
· std::cin 是 istream 类的对象,它主要⾯向窄字符(narrow characters (of type char))的标准输 ⼊流。
· std::cout 是 ostream 类的对象,它主要⾯向窄字符的标准输出流。
· std::endl 是⼀个函数,流插⼊输出时,相当于插⼊⼀个换⾏字符加刷新缓冲区。
· <<是流插入运算符,>>是流提取运算符。
· C++的输⼊ 输出可以⾃动识别变量类型,最重要的是 C++的流能更好的⽀持⾃定义类型对象的 输⼊输出。
· cout/cin/endl等都属于C++标准库,C++标准库都放在⼀个叫std(standard)的命名空间中,所以 要通过命名空间的使⽤⽅式去⽤他们。
#include<iostream>
using namespace std;
int main()
{
int rand = 10;
char c = 'x';
cout << rand << " " << c << endl;//打印 10 x
std::cout << rand << " " << c << std::endl;
//可以自动识别变量的类型
cin >> rand;
cin >> c;
cout << rand << endl;
cout << c << endl;
return 0;
}
4.缺省参数
· 缺省参数是声明或定义函数时为函数的参数指定⼀个缺省值。在调⽤该函数时,如果没有指定实 参则采⽤该形参的缺省值,否则使⽤指定的实参,缺省参数分为全缺省和半缺省参数。
· 全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往 左依次连续缺省,不能间隔跳跃给缺省值。
· 带缺省参数的函数调⽤,C++规定必须从左到右依次给实参,不能跳跃给实参。
· 函数声明和定义分离时,缺省参数不能在函数声明和定义中同时出现,规定必须函数声明给缺省 值。
#include<iostream>
using namespace std;
void Func(int a = 0)
{
cout << a << endl;
}
int main()
{
Func(); // 0 没有传参,使用参数的默认值
Func(10); // 10 传参,使用指定的实参
return 0;
}
4.1全缺省、半缺省
#include<iostream>
using namespace std;
//全缺省
void Func1(int a = 10, int b = 20, int c = 30)
{
cout << "a = " << a <<endl;
cout << "b = " << b <<endl;
cout << "c = " << c <<endl;
}
//半缺省
void Func2(int a, int b = 20, int c = 30)
{
cout << "a = " << a <<endl;
cout << "b = " << b <<endl;
cout << "c = " << c <<endl;
}
int main()
{
Func1(); //10 20 30
Func1(1); //1 20 30
Func1(1,2); //1 2 30
Func1(1,2,3);//1 2 3
Func2(1); //1 20 30
Func2(1,2); //1 2 30
Func2(1,2,3);//1 2 3
return 0;
}
4.2多文件缺省参数使用
4.2.1Stack.h
#include<iostream>
#include<assert.h>
using namespace std;
typedef int STDatatype;
typedef struct Stack
{
STDatatype* a;
int top;
int capacity;
}ST;
void STInit(ST* ps, int n = 4);//不给参数时要开辟空间的大小
4.2.2Stack.cpp
#include"Stack.h"
//缺省参数不能声明和定义同时给,只能给声明
void STInit(ST* ps, int n)
{
assert(ps && n > 0);
ps->a = (STDatatype*)malloc(n * sizeof(STDatatype));
ps->top = 0;
ps->capacity = n;
}
4.2.3test.cpp
#include<iostream>
int main()
{
ST st1;
STInit(&st1);//初始化开辟4个int大小的空间
ST st2;
STInit(&st2,1000);//初始化开辟1000个int大小的空间
return 0;
}
5.函数重载
C++⽀持在同⼀作⽤域中出现同名函数,但是要求这些同名函数的形参不同,可以是参数个数不同或者 类型不同。这样C++函数调⽤就表现出了多态⾏为,使⽤更灵活。C语⾔是不⽀持同⼀作⽤域中出现同名函数的。
5.1参数类型不同
int Add(int left, int right)
{
std::cout << "int Add(int left, int right)" << std::endl;
return left + right;
}
double Add(double left, double right)
{
std::cout << "double Add(double left, double right)" <<std::endl;
return left + right;
}
5.2参数个数不同
void f()
{
std::cout << "f()" << std::endl;
}
void f(int a)
{
std::cout<< "f(int a)" << std::endl;
}
5.3参数类型顺序不同
void f(int a, char b)
{
std::cout << "f(int a, char b)" << std::endl;
}
void f(char a, int b)
{
std::cout << "f(char a, int b)" << std::endl;
}
5.4问题
返回值不同不能作为重载条件,因为调用时也无法区分
void fxx()
{}
int fxx()
{
return 0;
}
缺省参数
//下面两个函数构成重载
//但是调用时,会报错,存在歧义,编译器不知道调用谁
void f1()
{
std::cout << "f1()" << std::endl;
}
void f1(int a = 10)
{
std::cout << "f1(int a)" << std::endl;
}
6.引用
引⽤不是新定义⼀个变量,⽽是给已存在变量取了⼀个别名,编译器不会为引⽤变量开辟内存空间, 它和它引⽤的变量共⽤同⼀块内存空间。
类型& 引用别名 = 引用对象;
#include<iostream>
using namespace std;
int main()
{
int a = 0;
int& b = a;
int& c = b;
c++;
//此打印的地址是相同的
cout << &a << endl;
cout << &b << endl;
cout << &d << endl;
return 0;
}
6.1特性
· 引⽤在定义时必须初始化
· ⼀个变量可以有多个引⽤
· 引⽤⼀旦引⽤⼀个实体,再不能引⽤其他实体
6.2使用
· 引⽤在实践中主要是于引⽤传参和引⽤做返回值中减少拷⻉提⾼效率和改变引⽤对象时同时改变 被引⽤对象。
· 引⽤传参跟指针传参功能是类似的,引⽤传参相对更⽅便⼀些。
· 引⽤和指针在实践中相辅相成,功能有重叠性,但是各有特点,互相不可替代。
//指针方法
void Swap(int* rx, int* ry)
{
int tmp = *rx;
*rx = *ry;
*ry = tmp;
}
//引用方法
void Swap(int& rx, int& ry)
{
int tmp = rx;
rx = ry;
ry = tmp;
}
int main()
{
int x = 0, y = 1;
std::cout << x << " " << y << std::endl;
Swap(x, y);
std::cout << x << " " << y << std:: endl;
return 0;
}
6.2.1引用替代指针传参
//栈实现
#include<iostream>
using namespace std;
typedef int STDatatype;
typedef struct Stack
{
STDatatype* a;
int top;
int capacity;
}ST;
void STInit(ST& rs, int n = 4)
{
rs.a = (STDatatype*)malloc(n * sizeof(STDatatype));
rs.top = 0;
rs.capacity = n;
}
void STPush(ST& rs, STDataType x)
{
assert(ps);
if (rs.top == rs.capacity)
{
printf("扩容\n");
int newcapacity = rs.capacity == 0 ? 4 : rs.capacity * 2;
STDataType* tmp = (STDatatype*)realloc(rs.a, newcapacity * sizeof(STDatatype));
if (tmp == NULL)
{
perror("realloc fail");
return;
}
rs.a = tmp;
rs.capacity = newcapacity;
}
rs.a[rs.top] = x;
rs.top++;
}
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);
cout << STTop(st1) << endl;
STTop(st1) += 10;
cout << STTop(st1) << endl;
return 0;
}
6.3const引用
· 可以引⽤⼀个const对象,但是必须⽤const引⽤。const引⽤也可以引⽤普通对象,因为对象的 访问权限在引⽤过程中可以缩⼩,但是不能放⼤。
· 不需要注意的是类似 int& rb = a*3; double d = 12.34; int& rd = d; 这样⼀些场景下a*3的和结果 保存在⼀个临时对象中, int& rd = d 也是类似,在类型转换中会产⽣临时对象存储中间值,也 就是时,rb和rd引⽤的都是临时对象,⽽C++规定临时对象具有常性,所以这⾥就触发了权限放 ⼤,必须要⽤常引⽤才可以。
· 所谓临时对象就是编译器需要⼀个空间暂存表达式的求值结果时临时创建的⼀个未命名的对象, C++中把这个未命名对象叫做临时对象。
int main()
{
const int a = 10;
int ra = a;//错误,无法从"const int"转换为"int&",对a权限放大
const int& ra = a;//正确
int b = 20;
const int& rb = b;//正确,对b访问权限的缩小
const int& rc = a * 3;//a * 3的结果保存在临时对象中,具有常性,触发权限放大,需要常引用
double d = 12.34;
const int& rd = d;//d类型从double转换为int时,结果保存在临时对象中
return 0;
}
6.4指针和引用关系
· 语法概念上引⽤是⼀个变量的取别名不开空间,指针是存储⼀个变量地址,要开空间。
· 引⽤在定义时必须初始化,指针建议初始化,但是语法上不是必须的。
· 引⽤在初始化时引⽤⼀个对象后,就不能再引⽤其他对象;⽽指针可以在不断地改变指向对象。
· 引⽤可以直接访问指向对象,指针需要解引⽤才是访问指向对象。
· sizeof中含义不同,引⽤结果为引⽤类型的⼤⼩,但指针始终是地址空间所占字节个数(32位平台 下占4个字节,64位下是8byte)
· 指针很容易出现空指针和野指针的问题,引⽤很少出现,引⽤使⽤起来相对更安全⼀些。
标签:ps,入门,rs,int,namespace,缺省,C++ From: https://blog.csdn.net/sjyioo/article/details/144458906