C++ primer 学习笔记1-7

学校只教过C和JAVA,C++是自己看的,始终还是喜欢C的风格。
对C++的很多特性始终都是一知半解,也许可以学习一些细节。

第一章 快速入门
cin(see-in)标准输入
cout(see-out)标准输出
cerr(see-err)标准错误
clog
后面3个在实现上的具体区别:
cout,cerr和clog的输出都可以重定向,比如文件,通过1> 和2>的不同来区别。
cout和clog的输出是有缓冲区的,缓冲区满或者遇到endl,cerr直接输出。
比如在代码里cout和cerr、clog,然后执行文件>1.txt,那么cout的内容到达1.txt,cerr、clog的内容到屏幕。
如果使用2>,即错误输出,那么结果相反。
#include <iostream>
using namespace std;
int main()
{
cout<<"cout"<<endl;
cerr<<"cerr"<<endl;
clog<<"clog"<<endl;
return 0;
}

运行g++ test.cpp
./a.out   那么全部输出屏幕
./a.out > 1.txt 那么屏幕输出cerr和clog,文本是cout
./a.out 2>1.txt   哪么屏幕输出cout,文本是cerr和clog

cin也是有返回值的
可以使用
int value;
while(cin>>value)……;
来输入数值,如果无效或者是EOF,则返回假。

(就这几行字,重打了好几次,QQ导致死机2次,遨游神秘退出一次)

第二章 变量和基本类型
初始化分:复制初始化和直接初始化。
int ival=1000;
int ival(1000);

string all_nines(10,‘9‘);//all_nines="9999999999"

流比printf好一点,就是string输出不用加讨厌的.c_str()了。无论是cin还是cout。

const int connum=0;定义一个常量,必须初始化,以前习惯了使用宏定义的,const只是在方法的传递参数时才会使用的,不过始终感觉不到在定义常数时,const比宏定义好哪里

定义在文件中的变量,非const变量默认为extern,如果加上const,那么这个常量就不能在这个文件以外的地方使用的了。除非extern const int connum = 0;

枚举是四个字节长度,每个成员都是int类型,可以初始化负数。

无论是c还是c++,struct都是默认实现=号赋值的。

第三章 标准库类型
cin忽略开头的空白字符(空格换行制表符)。读取时遇到空白字符,读取终止。
要读取一行用getline,不过忽略最后一个回车。
string line;
while(getline(cin,line))
cout<<line<<endl;
cout<<"ctrl + d"<<endl;
ctrl + d结束输入。

string的方法size()返回类型是string::size_type,无符号整型。
string的变量可以直接用数组的形式来操作,包括替换。比如string str1="123"; str1[1]=a;//str1="1a3"

P89页表3-3记录了对字母判断和操作的函数。或者看这里:
http://net.pku.edu.cn/~yhf/linux_c/function/01.html#linuxc1

装换大小写
for(size_type i=0;i!=s.size();++i)s[i]=tolower(s[i]);
其实也可以这样写:
transform(s.begin(),s.end(),s.begin(),tolower);
据说用stl最大的好处是可以抛弃for循环。

vector<int> ivec(10,-1)//10个成员,每个都是-1。不加第二个参数,默认给0
vector<string> svec(10,"hi")//10个成员,每个初始化赋值hi

迭代器iterator其实就是指针,但是注意,迭代器的++或者是--,不能对传入参数里面的迭代器操作,否则就会出错。

同时还提供了一个const_iterator,作用只可取值不能赋值。
这里需要区别 const iterator,这个可以赋值但是不能++或者-- 。

vector<int>::const_iterator it = vector1.begin();
*it=5;//错误,不能赋值

const vector<int>::iterator it = vector1.begin();
*it =5;//正确
it++;//错误,不能++

迭代器可以使用+n,或者-n操作。比如:
vector<int>::iterator mid = vi.begin() + vi.size()/2;

标准库bitset类型
这个我还一直没有用过。

和vector的区别在于尖括号里的长度而不是类型。
单位是位。bitset<32>bitvec(0xffff) 就是65536 。0到15位是1,16到31位是0 。
也可以用字符串来初始化:
string str("11100111"); bitset<32>bitves(str,5,3) //从第5位取3个值,那么就是0x111 。
cout<<bitves.to_ulong()<<endl; //输出7
cout<<bitves<<endl;//输出00000000000000000000000000000111

P90是bitset的方法。

第四章 数组和指针
无论是数组还是变量,在函数外定义的都是自动初始化0 ,在函数内定义的都是随机值。
如果成员是类,无论哪里定义,自动调用默认构造函数。

char a1[]={‘c‘,‘+‘,‘+‘};//打印a1,打印出了后面的乱码,一直到有0出现。

const int *a1;//*a1不可修改。a1可修改。
int *const a1;//如果指向的不是常量,那么*a1可修改。a1不可以修改。
const int *const a1;//*a1和a1都不可以修改。

这里有个很多人都会犯的错误。
typedef string *pstr;
const pstr cstr;
那么cstr是什么类型?
const string* cstr;//错误!
string *const cstr;//正确。

注意呀。

动态数组的初始化只能使用默认值0,比如:
int *pai = new int[10]();//所有值为0,小括号里不能给值,否则编译不过。

创建0个元素的数组不合法。但是创建0个元素的动态数组合法。
int a[0];//error
int *a = new int[0];//ok

第五章 表达式
&&优先级高于||

++i与i++区别:
前面的代码风格里已经说过了,后置的++会多复制一份对象出来,增加开销。不过对基础类型没有什么区别,因为编译器会做优化,但是对复杂类型就要有额外开销了。

如果程序耗尽的内存,new可能失败,系统抛出bad_alloc的异常,而不是返回NULL!
不过其实耗尽内存依然可以new成功,直到地址空间全部用完。

delete为0的指针是合法的操作,不会报错。

强制装换:
static_cast,dynamic_cast,const_cast,reinterpret_cast
实在实在是不喜欢用,直接用C的强制转换多方便,而且也看不出什么好处来
C的强制转换相当于reinterpret_cast。

第六章 语句
int i=0;
a[i]=b[i++];
结果是a[0]=b[0];i++;

抛出异常,是从内往外找处理语句。

都不处理则交给terminate标准库函数,一般处理是退出程序。

P189 表6-1 定义各种异常。
<exception>包括最常见的异常类。
<stdexcept>定义了几种常见异常,比如rumtime_error 使用的时候直接扔,如throw runtime_error("XXX");
<new>new失败的时候抛出bad_alloc异常,而不是返回NULL。
<type_info>定义了bad_cast

try{
……
throw runtime_error("XXX");
}
catch(runtime_error err)
{
cout<<err.what()<<endl;
}
输出XXX。
如果没有catch这个异常,显示异常类为什么,然后自动打印what内容,最后退出程序。
如果觉得每个异常都要写,就写一个也行,但是XXX就没有了。比如:
catch(exception err)
{
cout<<err.what()<<endl;
}
无论扔出什么异常,打印的结果都是St9exception
不知道有什么办法可以知道抛出的是什么异常呢?
或者:
catch(...)
{
}
什么都不处理。

原来while还可以使用多个条件,如while(i<5 , j<6){}

编译处理器里面生成的宏,在代码里可以使用。以前我一直以为是vc的东西,原因是标准c的东西。
__FILE__ 文件名
__LINE__ 该行的行号
__TIME__ 编译时间
__DATE__ 编译日期

第七章 函数

内联函数类似宏定义,在编译的时候自动替换成函数的内容,避免了写成函数的额外执行开销。

内联函数的定义需要写在头文件里。
还是喜欢宏定义。

时间: 2024-09-29 04:03:33

C++ primer 学习笔记1-7的相关文章

C++ Primer 学习笔记_98_特殊工具与技术 --优化内存分配

特殊工具与技术 --优化内存分配 引言: C++的内存分配是一种类型化操作:new为特定类型分配内存,并在新分配的内存中构造该类型的一个对象.new表达式自动运行合适的构造函数来初始化每个动态分配的类类型对象. new基于每个对象分配内存的事实可能会对某些类强加不可接受的运行时开销,这样的类可能需要使用用户级的类类型对象分配能够更快一些.这样的类使用的通用策略是,预先分配用于创建新对象的内存,需要时在预先分配的内存中构造每个新对象. 另外一些类希望按最小尺寸为自己的数据成员分配需要的内存.例如,

C++ Primer 学习笔记_73_面向对象编程 --再谈文本查询示例

面向对象编程 --再谈文本查询示例 引言: 扩展第10.6节的文本查询应用程序,使我们的系统可以支持更复杂的查询. 为了说明问题,将用下面的简单小说来运行查询: Alice Emma has long flowing red hair. Her Daddy says when the wind blows through her hair, it looks almost alive, like a fiery bird in flight. A beautiful fiery bird, he

C++ Primer 学习笔记_74_面向对象编程 --再谈文本查询示例[续/习题]

面向对象编程 --再谈文本查询示例[续/习题] //P522 习题15.41 //1 in TextQuery.h #ifndef TEXTQUERY_H_INCLUDED #define TEXTQUERY_H_INCLUDED #include <iostream> #include <fstream> #include <sstream> #include <vector> #include <set> #include <map&g

C++ Primer 学习笔记_19_类与数据抽象(5)_初始化列表(const和引用成员)、拷贝构造函数

C++ Primer 学习笔记_19_类与数据抽象(5)_初始化列表(const和引用成员).拷贝构造函数  从概念上将,可以认为构造函数分为两个阶段执行: 1)初始化阶段: 2)普通的计算阶段.计算阶段由构造函数函数体中的所有语句组成. 一.构造函数初始化列表 推荐在构造函数初始化列表中进行初始化 1.对象成员及其初始化 <span style="font-size:14px;">#include <iostream> using namespace std;

C++ Primer 学习笔记_14_标准模板库_bitset位集合容器

C++ Primer 学习笔记_14_标准模板库_bitset位集合容器 bitset容器是一个bit位元素的序列容器,每个元素只占一个bit位,取值为0或1,因而很节省内存空间.下图是一个bitset的存储示意图,它的10个元素只使用了两个字节的空间. 使用bitset需要声明头文件"#include <bitset>" 1.创建bitset对象 创建bitset对象时,必须要指定容器的大小.bitset对象的大小一经定义,就不能修改了.下面这条语句就定义了bitset对

C++ Primer 学习笔记_23_标准模板库_stack.

C++ Primer 学习笔记_11_标准模板库_stack.queue队列容器与priority_queue优先队列容器 1.stack堆栈 stack堆栈是一个后进先出(Last In First Out,LIFO)的线性表,插入和删除元素都只能在表的一端进行.插入元素的一端称为栈顶,而另一端称为栈底.插入元素叫入栈(Push),删除元素叫出栈(Pop).下图是堆栈示意图 堆栈只提供入栈,出栈,栈顶元素访问和判断是否为空等几种方法.采用push()方法将元素入栈:采用pop()方法出栈:采用

C++primer学习笔记(二)——Chapter 4

4.1  Fundamentals 1.Basic Concepts (1)操作符分为一元,二元或者三元操作符: (2)复杂的表达式中含有很多操作符时: 规则一:分为不同的级别,级别高的先运行: 规则二:相同级别的操作符有执行顺序的确定: (3)操作符可以改变操作数的类型 一般将级别低的转化成级别高的 (4)重载运算符 相同的运算符在对不同类型的对象进行操作的时候,会有不同的功能: (5)Lvalue和Rvalue 显而易见:Lvalue指的是Left value,Rvalue指的是Right

C++ Primer 学习笔记_104_特殊工具与技术 --嵌套类

特殊工具与技术 --嵌套类 可以在另一个类内部(与后面所讲述的局部类不同,嵌套类是在类内部)定义一个类,这样的类是嵌套类,也称为嵌套类型.嵌套类最常用于定义执行类. 嵌套类是独立的类,基本上与它们的外围类不相关,因此,外围类和嵌套类的对象是互相独立的.嵌套类型的对象不具备外围类所定义的成员,同样,外围类的成员也不具备嵌套类所定义的成员. 嵌套类的名字在其外围类的作用域中可见,但在其他类作用域或定义外围类的作用域中不可见.嵌套类的名字将不会与另一作用域中声明的名字冲突 嵌套类可以具有与非嵌套类相同

C++ Primer 学习笔记_102_特殊工具与技术 --运行时类型识别[续]

特殊工具与技术 --运行时类型识别[续] 三.RTTI的使用 当比较两个派生类对象的时候,我们希望比较可能特定于派生类的数据成员.如果形参是基类引用,就只能比较基类中出现的成员,我们不能访问在派生类中但不在基类中出现的成员. 因此我们可以使用RTTI,在试图比较不同类型的对象时返回假(false). 我们将定义单个相等操作符.每个类定义一个虚函数 equal,该函数首先将操作数强制转换为正确的类型.如果转换成功,就进行真正的比较:如果转换失败,equal 操作就返回 false. 1.类层次 c

C++ Primer 学习笔记_77_模板与泛型编程 --实例化

模板与泛型编程 --实例化 引言: 模板是一个蓝图,它本身不是类或函数.编译器使用模板产生指定的类或函数的特定版本号.产生模板的特定类型实例的过程称为实例化. 模板在使用时将进行实例化,类模板在引用实际模板类型时实例化,函数模板在调用它或用它对函数指针进行初始化或赋值时实例化. 1.类的实例化 当编写Queue<int>qi时,编译器自己主动创建名为Queue<int>的类.实际上,编译器通过又一次编写Queue模板,用类型int取代模板形參的每次出现而创建Queue<int