C++入门基础知识
1.C++兼容C
//.c
#include<stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
//.cpp
#include<iostream>
using namespace std;
int main()
{
cout << "hello world\n" << endl;
return 0;
}
2.命名空间
在C/C++的学习中,变量,函数名以及类这些东西,定义在全局定义域中,会导致很多重突,
//命名空间就是将这些东西进行本地化,防止冲突。
namespace命名空间域的关键字
#include <stdlib.h>
int rand = 10;
int main()
{
// 编译报错:error C2365: “rand”: 重定义;以前的定义是“函数”
printf("%d\n", rand);
return 0;
}
namespace的定义
1.namespace后面跟命名空间名,{命名空间的成员变量},{}里面是变量,函数,类型。
2.namespace的本质是定义出一个域,这个域于全局域互相独立,所以就解决了变量冲突
3.C++中有全局域,局部域,命名空间域,类域。域影响的是编译时,语法查找一个变量/函数/类型出处的逻辑,有了域的隔离,命名冲突问题也就解决了。
局部域和全局域不仅影响语法查找逻辑,还影响变量的生命周期。命名空间域和类域不影响变量的生命周期。
4.namespace只可以在全局定义,也可以嵌套定义。
5.项目中多文件中有多个namespace,会被认为是一个,不会冲突。
6.C++标准库都放在一个std(standard)的命名空间中。
//#include<stdio.h>
//#include<stdlib.h>
//namespace只能定义在全局内,可以嵌套定义
namespace jiege
{
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
//zhangsan和lisi属于不同的域,但可以定义相同的变量
namespace zhangsan
{
int rand = 1;
int Add(int left, int right)
{
return left + right;
}
}
namespace lisi
{
int rand = 2;
int Add(int left, int right)
{
return (left + right) * 10;
}
}
}
#include<iostream>
using namespace std;
int main()
{
struct jiege::Node* node = { 0 };
scanf("%d ",node->val );
cin>>node->val;
cout << jiege::Add(1, 5) << endl;
printf("%d \n", jiege::zhangsan::rand);
printf("%d \n", jiege::lisi::rand);
return 0;
}
//多文件命名相同名字的namespace会认为是一个namespace,不会冲突
命名空间的使用
1.编译查找的时候只会在全局域和局部域,不会到命名空间里面去找。
想要使用命名空间里面的成员变量,有以下三种方式
a.指定命名空间进行访问
b.展开命名空间的部分成员
c.展开命名空间内的全体成员
//#include<iostream>
//namespace jiege
//{
// int a;
// int b;
//}
////项目中经常访问的不存在冲突的变量
//using jiege::b;
////展开命名空间中全部的成员
using namespace jiege
//int main()
//{
// printf("%d\n", b);
// //指定命名空间进行访问
// //printf("%d\n", jiege::a);
// return 0;
//}
3 C++的输入与输出
1.<iostream>是标准的输入输出流库,定义了标准的输入输出对象。
2.std::cin istream类的对象他主要面向窄字符的标准输入流。
3std::cout ostream类的对象,面向窄字符的标准输出流。
4.std::endl 是一个函数,流插入输入时,相当于换行字符➕一个刷新缓冲区
5.<<是流插⼊运算符,>>是流提取运算符。
6.使用C++的输入输出会更加方便,不需要C语言中printf scanf 进行手动指定格式,C++的输入输出自动识别变量类型(本质是通过函数重载)C++会更好的支持自定义类型的输入输出。
//输入或输出
//#include<iostream>
//using namespace std;
//int main()
//{
// int a = 10;
// double b = 0.11111;
// char c = 'x';
// cin >> a >> b >> c;
// cout << a <<' ' << b <<'\n'<< c << endl;
//
// return 0;
//}
//#include<iostream>
//using namespace std;
//int main()
//{
// // 在io需求⽐较⾼的地⽅,如部分⼤量输⼊的竞赛题中,加上以下3⾏代码
// // 可以提⾼C++IO效率
// ios_base::sync_with_stdio(false);
// cin.tie(nullptr);
// cout.tie(nullptr);
// return 0;
//}
4.缺省函数
缺省函数是在定义或声明时为函数参数指定一个缺省值,在调用该函数时,如果没有指定实参,则采用该形参的缺省值。否则使用指定的实参,缺省参数有全缺省和半缺省(缺省参数也可以叫默认参数)
全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定必须从左到右依次给缺省值,不能跳跃型给缺省值。
带缺省函数的调用,必须从左到右依次给缺省值,不能跳跃的给缺省值。
函数的定义与声明分开时,缺省参数不能同时在定义和声明里面出现,C++规定函数声明给缺省值
//缺省参数
#include<iostream>
using namespace std;
//void Func(int a = 10)
//{
// cout << a << endl;
//}
//int main()
//{
// Func();
// Func(0);
// return 0;
//}
// 全缺省
//void Func1(int a = 10, int b = 20, int c = 30)
//{
// cout << "a = " << a << endl;
// cout << "b = " << b << endl;
// cout << "c = " << c << endl << endl;
//}
//// 半缺省
//void Func2(int a, int b = 10, int c = 20)
//{
// cout << "a = " << a << endl;
// cout << "b = " << b << endl;
// cout << "c = " << c << endl << endl;
//}
//int main()
//{
// Func1();
// Func1(1);
// Func1(1, 2);
// Func1(1, 2, 3);
// Func2(100);
// Func2(100, 200);
// Func2(100, 200, 300);
// return 0;
//}
void STInit(ST* ps, int n = 4);
// Stack.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;
}
// test.cpp
#include"Stack.h"
int main()
{
ST s1;
STInit(&s1);
// 确定知道要插⼊1000个数据,初始化时⼀把开好,避免扩容
ST s2;
STInit(&s2, 1000);
return 0;
}
5.函数重载
#include<iostream>
using namespace std;
// 1、参数类型不同
int Add(int left, int right)
{
cout << "int Add(int left, int right)" << endl;
return left + right;
}
double Add(double left, double right)
{
cout << "double Add(double left, double right)" << endl;
return left + right;
}
// 2、参数个数不同
void f()
{
cout << "f()" << endl;
}
void f(int a)
{
cout << "f(int a)" << endl;
}
// 3、参数类型顺序不同
void f(int a, char b)
{
cout << "f(int a,char b)" << endl;
}
void f(char b, int a)
{
cout << "f(char b, int a)" << endl;
}
// 返回值不同不能作为重载条件,因为调⽤时也⽆法区分
//void fxx()
//{}
//
//int fxx()
//{
// return 0;
//}
// 下⾯两个函数构成重载
// f()但是调⽤时,会报错,存在歧义,编译器不知道调⽤谁
void f1()
{
cout << "f()" << endl;
}
void f1(int a = 10)
{
cout << "f(int a)" << endl;
}
int main()
{
Add(10, 20);
Add(10.1, 20.2);
f();
f(10);
f(10, 'a');
f('a', 10);
return 0;
}
6.引用
1引用的定义
引用就是给变量取别名,它与变量共用同一块空间。
int main()
{
int a = 0;
// 引⽤:b和c是a的别名
int& b = a;
int& c = a;
// 也可以给别名b取别名,d相当于还是a的别名
int& d = b;
++d;
// 这⾥取地址我们看到是⼀样的
cout << &a << endl;
cout << &b << endl;
cout << &c << endl;
cout << &d << endl;
return 0;
}
2引用的特性
引用在定义时必须初始化
一个变量可以有多个引用
一旦引用了一个实体,就不能引用其他实体
//int main()
//{
// int a = 0;
// //int& ra;
// int& b = a;//创建以后必须初始化
// int c = 20;
// //int&c = a;
// b = c;//这是一个赋值
// //一个变量可以有多个引用
// //引用一旦有了实体,就不能引用其他实体
// cout << &a << endl;
// cout << &b << endl;
// cout << &c << endl;
// return 0;
//}
//void Swap(int& rx, int& ry)
//{
// int tmp = rx;
// rx = ry;
// ry = tmp;
//}
//int main()
//{
// int x = 0, y = 1;
// cout << x << " " << y << endl;
// Swap(x, y);
// cout << x << " " << y << endl;
// return 0;
//}
//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;
//}
3引用的使用
引用传参和引用做返回值,减少拷贝,提升效率,改变引用对象的同时改变被引用对象
//引用做返回值
//int& STTop(ST& rs)
//{
// //assert(rs.top > 0);
// return rs.a[rs.top];
//}
//// 栈顶
//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 main()
//{
// ST st;
// STInit(st);
// STTop(st) = 3;//直接改变栈顶元素的值
// cout << STTop(st) << endl;
// return 0;
//}
3Const引用
//int main()
//{
// const int a = 10;//此时a具有常属性只可以读
// //int& ra = a;
// const int& ra = a;//引用所产生的别名权限必须与原来小于等于
// //临时对象具有常性
// //表达式的结果
// //常量
// //隐式类型转换
// //引用以后临时变量的生命周期随着引用走
// const int& rb = 30;
// int b = 30;
// const int& rb = b;
// const int&rd=(a + b);
// int rd = (a + b);//这是一种赋值拷贝
//
//
// //这里是权限放大
// const int a = 10;//此时a具有常属性只可以读
// //int& ra = a;
// //单纯的拷贝给另一个,不存在权限放大
// const int a = 10;
// int rd = a;
// //int& rd=(a+b);
//
// double d = 12.34;
// int i = d;
// const int& ri = d;
//
//
// return 0;
//}
4指针和引用的关系
7.inline
inline修饰的函数叫内联函数,C++在编译的时候会在调用的地方展开内联函数,这样就不需要额外的建立函数栈帧,就可以提高效率
//inline 不建议声明和定义在两个文件中,导致链接错误
//inline 函数直接定义在.h文件中
//inline void Swap(int& x, int& y)
//{
//
//}
//int main()
//{
// int a = 10, b = 0;
// Swap(a, b);
//
// return 0;
//}
//int ADD(int& a, int& b)
//{
// return a + b;
//}
//// 为什么不能加分号?
//// 为什么要加外⾯的括号?
//// 为什么要加⾥⾯的括号?
//#define ADD(a,b) ((a)+(b))
//int main()
//{
// cout << ADD(1, 2) << endl;
// cout << ADD(1, 2)*5 << endl;
// int x = 1, y = 2;
// ADD(x & y, x | y); //如果没有括号的话等价于 -> (x&y+x|y)
// return 0;
//}
8.nullptr
//nullptr
//NULL在C++文件中定义为字面常量0
//NULL在c文件中被定义为(void*)0
//C++11中引⼊nullptr,nullptr是⼀个特殊的关键字,nullptr是⼀种特殊类型的字⾯量,它可以转换
//成任意其他类型的指针类型。使⽤nullptr定义空指针可以避免类型转换的问题,因为nullptr只能被
//隐式地转换为指针类型,⽽不能被转换为整数类型。
//void f(int x)
//{
// cout << "f(int x)" << endl;
//}
//void f(int* ptr)
//{
// cout << "f(int* ptr)" << endl;
//}
//int main()
//{
// //f(0);
// //f((void*)0);
// int* p1 = nullptr;
// //int p2 = nullptr;
//
// return 0;
//}
更多推荐


所有评论(0)