C++初阶1:入门
目录
一、前言
C++是一种广泛使用的高级编程语言,最早由比尔·古德斯特(Bjarne Stroustrup)在1979年于AT&T贝尔实验室研发。C++的设计初衷是为了在保留C语言高效和灵活性的基础上,增加面向对象编程的能力。
所以C++其实是可以兼容C语言的,而且C++更像是把C语言中一些不好解决并且复杂的东西变得简单化。
二、第一个C++程序
我们在学习C语言时写的第一个程序是
#include <stdio.h>
int main()
{
printf("hello world\n");
return 0;
}
那我们在学习C++的时候也是如此,上面的代码在C++的环境下也可以执行,但我们更正宗的写法是
#include <iostream>
using namespace std;
int main()
{
cout << "hello world" << '\n' << endl;
return 0;
}
我们接下来就帮助大家看懂这个代码
三、命名空间
C++这个命名空间的概念可以帮助我们解决下面这种命名定义重复的问题

namespace是一个关键字,后面跟命名空间的名字,然后接⼀对{}即可,{}中即为命名空间的成员。命名空间中可以定义变量/函数/类型等。如下
namespace cqw
{
int rand = 10;
int Add(int left, int right)
{
return left + right;
}
struct Node
{
struct Node* next;
int val;
};
}
int main()
{
printf("%p\n", rand);
printf("%d\n", cqw::rand);
return 0;
}
第一个rand是头文件stdlib中的函数,所以打印出了它的指针,第二个rand是命名空间cqw中的变量,所以打印出了它的值。

四、输入和输出
<iostream> 提供,主要使用
cin(标准输入)、
cout(标准输出)和
cerr(标准错误流)。
#include<iostream>
using namespace std;
int main()
{
cout << "10" << '\n' << "20" << endl;
cout << "10" << '\n' << endl;
std::cout << "20" << '\n' << endl;
return 0;
}
int main()
{
int a = 0;
int b = 0;
cin >> a;
cout << a << endl;
cin >> a >> b;
cout << a << ' ' << b << endl;
return 0;
}
多练习才能熟练。
五、缺省参数
void Foun(int a = 10)
{
cout << a << endl;
}
int main()
{
Foun();
Foun(20);
return 0;
}
全缺省就是全部形参给缺省值,半缺省就是部分形参给缺省值。C++规定半缺省参数必须从右往左 依次连续缺省,不能间隔跳跃给缺省值。 带缺省参数的函数调用,C++规定必须从左到右依次给实参,不能跳跃给实参。
// 全缺省
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;
}
#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);
void STInit(ST* ps, int n)
{
assert(ps && n > 0);
ps->a = (STDataType*)malloc(n * sizeof(STDataType));
ps->top = 0;
ps->capacity = n;
}
六、函数重载
#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;
//}
//
//构成重载但f1()会报错
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;
}
七、引用
#include <iostream>
using namespace std;
int main()
{
int a = 0;
int& b = a;
int& c = a;
int& d = b;
a++;
cout << a << endl;
cout << b << endl;
cout << c << endl;
cout << d << endl;
return 0;
}
引用传参和指针传参的功能很类似,而且在一定情况下引用传参比指针传参更加方便。就比如我们之前写过的交换数字的函数。
//指针
void Swap(int* p, int* q)
{
int tmp = *p;
*p = *q;
*q = tmp;
}
//引用
void Swap2(int& p, int& q)
{
int tmp = 0;
tmp = p;
p = q;
q = tmp;
}
int main()
{
int x = 0, y = 1;
cout << x << " " << y << endl;
Swap(&x, &y);
cout << x << " " << y << endl;
int a = 3, b = 4;
cout << a << " " << b << endl;
Swap2(a, b);
cout << a << " " << b << 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;
}
// 栈顶
void STPush(ST& rs, STDataType x)
{
// 满了, 扩容
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)
int& STTop(ST& rs)
{
assert(rs.top > 0);
return rs.a[rs.top - 1];
}
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;
}
const引用
int main()
{
//err
//放大权限
const int a = 0;
int& b = a;
//缩小权限
int a = 0;
const int& b = a;
//
const int a = 0;
const int& b = a;
return 0;
}
还有下面一些类型转化和常量情况下有权限放大的风险,所以必须用const引用。
int main()
{
int a = 10;
int& b = 30;//错误,常量涉及访问权限放大
const int& b = 30;//正确
int& ra = a * 3;//错误,a*3是临时对象具有常性涉及访问权限放大
const int& ra = a * 3;//正确
double d = 12.1;
int& rb = d;//错误,类型转化涉及访问权限放大
const int& rb = d;//正确
return 0;
}
C++中指针和引⽤就像两个性格迥异的亲兄弟,指针是哥哥,引⽤是弟弟,在实践中他们相辅相成,功能有重叠性,但是各有⾃⼰的特点,互相不可替代。
语法概念上引⽤是⼀个变量的取别名不开空间,指针是存储⼀个变量地址,要开空间。引⽤在定义时必须初始化,指针建议初始化,但是语法上不是必须的。引⽤在初始化时引⽤⼀个对象后,就不能再引⽤其他对象;⽽指针可以在不断地改变指向对象。 引⽤可以直接访问指向对象,指针需要解引⽤才是访问指向对象。sizeof中含义不同,引⽤结果为引⽤类型的⼤⼩,但指针始终是地址空间所占字节个数(32位平台下占4个字节,64位下是8byte) 。指针很容易出现空指针和野指针的问题,引⽤很少出现,引⽤使⽤起来相对更安全⼀些。
八、inline
//用宏
#define ADD(x,y) ((x)+(y))
//用内联函数
inline int ADD1(int x, int y)
{
return x + y;
}
int main()
{
int a = ADD(10, 20);
cout << a << endl;
int b = ADD1(1, 2);
cout << b << endl;
return 0;
}
乍一看是不是认为宏还好,但正是因为宏是直接代替所以有很多麻烦,就像我们刚刚写个简单的加法函数还需要考虑那么多,加那么多括号也是因为我们需要考虑直接代替会有一系列操作符的优先顺序的问题。
// F.h
#include <iostream>
using namespace std;
inline void f(int i);
// F.cpp
#include "F.h"
void f(int i)
{
cout << i << endl;
}
// main.cpp
#include "F.h"
int main()
{
f(10);
return 0;
}
九、nullptr
#ifndef NULL
#ifdef __cplusplus
#define NULL 0
#else
#define NULL ((void *)0)
#endif
#endif
void f(int x)
{
cout << "f(int x)" << endl;
}
void f(int* ptr)
{
cout << "f(int* ptr)" << endl;
}
int main()
{
f(0);//no
f(NULL);//no
f((int*)NULL);//no
f(nullptr);//yes
return 0;
}
更多推荐


所有评论(0)