【基础知识】C++ (一)

C++基础知识



前言

参考文献:C++ primer 中文版 (第五版)

一、开始

IDE 集成开发环境
编写一个简单的C++程序

int main(){
    return 0;
}

初认识输入输出:

向流写入数据:有一个关键的要点,cout运算符接受两个运算对象,左侧的运算对象必须是一个ostream对象,右侧的对象是要打印的值。运行连在一起以后,就可以把输入连起来。endl是一个操作符的特殊值,他可以将与设备关联的缓冲区刷新到设备中且结束当前行。
C++的注释有两种 // 和/ * */ 这与python那两种完全不一样 注释界定符是不能嵌套的
读取数量不定的输入数据:(之前考研复试复习C++见过)

#include <iostream>
int main(){
    int sum = 0, value = 0;
    while(std:cin >> value)
        sum += value;
    std:cout << "Sum is:" << sum << std:endl;
    return 0;
}

二、变量与基本数据类型

1.基本内置类型

C++定义了一套关于算数类型和空类型在内的基本数据类型。当函数在不返回任何值时使用空类型作为返回类型。
int类型几个字节与编译器有关 书上是两个 不过在gcc 上大部分是4个
具体类型占用多少字节忘了要去看书:
类型转换

bool b = 42   //b 为真
int i = b;  // i=1
i = 3.14  //i=3
double pi = i; //pi的值是3.0
unsigned char c = -1;//c =255
signed char c2 = 256 //没有256

unsigned u1 = 42,u2 = 10;
std:cout << u1 - u2 <<std:endl; //32
std:cout << u2 - u1 <<std:endl; //正确 不过是取模后的值
//-1 取模以后是4294967295  无符号数和带符号一起操作  带符号数会被转换为无符号数

当带符号值和无符号值一起运算时,带符号值会自动转换为无符号值

字面值常量
20 十进制数 020 八进制数 0x20 十六进制数
整型和浮点型字面值
字符和字符串字面值 转义序列
转义序列包括换行符 ,横向制表符 ,反斜线等组成。转义序列除了有\n、\t等常见的东西组成。我们也可以使用泛化的转义序列,其形式是\x后面紧跟一个或多个十六进制数字,或者\后面紧跟1个、2个、3个八进制数字。其中数字部分表示的是字符对应的数值。例子如下:

std:cout<<"hi \x4do\115!\n" //这里本质就是输出hi MoM! 并转到新一行

如果反斜杠后面的数字超过三个,那么只有前三个构成转义数字,而相反\x要用后面跟着的所有数字


## 2.变量 变量定义 C++11以来变量的初始化可以用大括号来表示了,但如果将double变量初始化int变量时,大括号的赋值方法将会报错,因为他并不会进行隐式转换。 如果变量未初始化,如果变量在任何函数体外,那么他是0,如果在块作用域内,那么他的值是不知道的。 变量声明和定义的关系比较简单。 标识符和C语言相同。
## 3.复合类型 引用其实是别名,引用为对象起了个名字,引用类型引用另外一种或类型
int ival = 1024;
int &refVal = ival;
int &refVal2;//这是错误的  引用必须初始化  引用实质上是别名
// 引用只能绑定在对象上   而且引用的数据类型必读与被引用对象严格一致
refVal = 2;
int ii = rsfVal; //与ii=ival执行结果相同

int &refVal3 = refVal;
int i = refVal ; //这些都是正确的
//引用的类型要与绑定的对象严格匹配
int &refVal4 = 10; //错误 必须绑定一个对象 不能是字面值
double dval = 3.14;
int &refVal5 = dval;// 错误 此处的引用类型的初始值必须是int对象,引用只能绑定在对象上,而补鞥与字面值或某个表达式的计算结果绑定在一起。

指针
指针是指向另外一种类型的复合类型,指针与引用有很大的不同。第一,指针本身就是一个对象,允许对指针赋值和复制,而且在指针周期可以先后指向多个对象。其二,指针无需在定义时赋值,和其他内置类型一样,在块作用域定义的指针如果没有初始化,将拥有一个不确定的值。

//指针的精髓
int *ip1, *ip2;
double dp ,*dp2;//声明了指向int的指针 一个double类型的变量和指向double类型的指针

int ival = 42
int *p = &ival;//获取对象的地址  由于引用没有对象  没有地址 所以不能定义指向引用的指针

double dval;
double *pd = &dval;
double *pd2 = pd;//都是正确的

int *pi = pd;//错误 不匹配
pi = &dval;//不对 想取地址不匹配

//使用指针访问对象 
int ival = 42;
int *p = &ival;
cout << *p;

//空指针
int *p = nullptr;//也可以用
int *p2 = 0;//来表示空指针 可以用0来初始化指针*p2  但是不能把int类型值为0的变量赋予指针
// 建议初始化所有指针
// 赋值和指针
int i = 42;
int *pi = 0;
int *pi2 = &i;
int *pi3;
pi3 = pi2;
pi2 = 0;
//其他指针操作
if(pi)
    //???
if(pi2)
    // ??? 用来判断指针是否为空的选择结构

void指针
void 是一种特殊的指针类型,可以存放任意对象的地址。一个void*指针存放一个地址,这一点和其他指针相似,但是不知道指向地址的类型

double obj = 3.14, *pd = &obj;
void *pv = &obj;
pv = pd; 
//指向指针的指针和指向指针的引用
int ival = 1024;
int *pi = &ival;
int **ppi = &pi;
**ppi
int i = 42;
int *p;
int *&r = p;
r = &i;
*r = 0;

4.const限定符

比较难的一部分 看了好半天。
我们想定义这样的一个变量,它的值不能被改变。

const int bufsize = 512;//这样任意修改它的值都是错误的 

const int i = get_size();
const int j = 421;
const int k; //运行时初始化 和 编译时初始化  第三个错误 必须赋值
//const与初始化
int i = 42;
const int ci = i;
int j = ci; //常量特征仅仅在执行改变他的内容时才有效,初始化都是合法的

默认状态下,const对象仅在文件内有效。
为了能在多个文件中共享。`

extern const int bufSize =  fcn();
extern const int bufSize;

const的引用
可以将引用绑定到const对象上,就像绑到其他变量上一样,我们称之为对常量的引用。只不过与普通引用不同,对常量的引用不能修改它所绑定的对象。这一点在复制构造函数那很有用!!!

const int ci = 1024const int &r1 = ci;
r1 = 42;//错误
int &2 = ci;//错误 试图让一个非常量引用指向常量对象

int i = 42const int &r1 = i;//允许一个常量引用绑定到一个普通的int类型上
//引用的类型必须与其所引用的对象的类型一致,但有2个例外。1是在初始化常量引用时允许用任意表达式作为初始值,只要该表达式的结果能转换成引用的类型即可。第二,允许一个常量引用绑定非常量的对象、字面值、甚至是一般表达式。
const int &r2 = 42; //合法
const int &r3 = r1 * 2; //合法
int &r4 = r1 * 2 //报错

原因是常量引用实际上是绑定了一个临时量。具体参考书目55页。下面简单说明:

double dval = 3.14;
const int &ri = temp;
//实际上是这么执行的
const int temp = dval;
const int &ri = temp;//引用的其实是临时量

//对const的引用可能引用一个非const对象
int i = 42;
int &r1 = i;
const int &r2 = =i;
r1 = 0;//对
r2 = 0;//错误

如果普通引用合法,那么将改变中间量,改变不了绑定变量,因此判定不合法。
尽管绑定对象不常量,不能通过更改常量引用去修改绑定值。

指针与const
指向常量的指针不能用于改变其所指对象的值。要想存放常量对象的地址,必须使用指向常量的指针:

const double  pi = 3.14;
double *ptr = &pi;//XXXXXXptr只是一个常量指针
const double  *cptr = &pi;
*cptr = 42;//报错

double dval = 3.14;
cptr = &daval//正确 只是不能更改该值

const指针
允许把指针定义为常量。常量指针必须初始化,而且一旦初始化,指针地址不能改变;

int errNumb = 0;
int *const curErr = &errNumb;
const double pi = 3.14159;
const double *const pip = &pi;//pip是一个指向常量对象的常量指针

常量指针只是地址不变,但可以改变量的值

因此常量指针被称为顶层const 指向常量的指针被称为底层const
这里十分复杂,看了好几遍书,肯定要多看看。
contexptr和常量表达式
C++11标准规定,允许变量声明为constexpr类型以便由编辑器来验证变量的值是否是一个常量表达式。声明为constexpr的变量一定是一个常量,而且必须使用常量表达式来初始化

constexpr int mf = 20;
constexpr int limit = mf + 1;
constexpr int sz = size();//只有当size是一个constexpr函数时,才是一条正确的语句

指针和constexpr
constexpr仅仅对指针有效。

const int *p = nullptr//p是指向一个整形常量的指针
constexpr int *q = nullptr//q是一个指向整数的常量指针
//仅仅地址是常量 constexpr指向的对象可以不是常量
constexpr int *np = nullptr;// np是一个指向整数的常量指针
int j = 0;
constexpr int i = 42; //ij必须定义在函数体之外 要不然地址不唯一  违背了constexpr的思想
constexpr const int *p = &i;//常量指针指向整型常数
constexpr  int *p1 = &j;//常量指针指向整数

5.处理类型

生成别名
C++11保留了typedf double wages;还有了新的方法:using SI = Sales_item;
指针常量类型别名别用错
aoto语句在一条生命语句中只能有一个基本数据类型。

auto i = 0 ,*p =&i;//正确
auto sz = 0, pi = 3.14;//错误·

decltype类指示符


6.自定义数据结构

编写自己的头文件
为了确保各个文件中类的定义一致,类通常定义在头文件中,而且类的头文件名字应该与类的名字相同。例如,库类型string在名为string的头文件中定义。
预处理器
#define指令把一个名字设定为预处理变量,另外两个指令则分别检查某个指定的预处理变量是否被定义:#ifdef当且仅当变量已定义时为真,#idndef当且仅当变量未定义时为真。一旦检查结果为真,则会一值执行到#endif那里。


总结

提示:这里对文章进行总结:
const这块真的要多理解理解

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

romanceQAQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值