《C++Primer》基本类型 标准库

● std:count<<”Enter two numbers:”<<std:endl;

输出操作返回的值是输出流本身,endl是一个操纵符,将它写入输出流时,具有输出换行的效果,并刷新与设备相关联的缓冲区。

 

● C++算术类型

image

 

● 在32位机器中int类型和long类型通常字长是相同的,都是4个字节。

 

● 有些语言中将负数赋值给unsigned类型是非法的,但是在C++中这是合法的,所以,如果把-1赋给8位的unsigned char,那么结果是255,因为255是-1对256求模后的值。

 

● ‘a’ ‘2’ ‘,’这些字面值都是char类型的,在字符字面值前加L就能够得到wchar_t类型的宽字符字面值。  L’a’

 

● 不能连接字符串字面值和宽字符字面值。

 

● 在一行的末尾加一反斜线符号可将此行和下一行当做同一行处理。

std:cout<<”a multi-line\

                    string literal\

                    using a backslash”<<std::endl;

 

● 左值:左值可以出现在赋值语句的左边或者右边。

   右值:右值只能出现在赋值语句的右边,不能出现在赋值语句的左边。

 

● C++关键字

image

 

● C++支持两种初始化变量的形式:复制初始化和直接初始化。

int ival(1024);             //直接初始化

int ival = 1024;            //复制初始化

直接初始化语法更灵活且效率更高!

std:string all_nines(10,’9’);                 //all_nines = “9999999999”;

初始化不是赋值:初始化是指创建变量并给它赋初始值,而赋值则是擦除对象的当前值并用新值代替。

 

● 声明和定义:

变量的定义用于为变量分配储存空间,还可以为变量指定初值,在一个程序中,变量有且仅有一个定义。

声明用于向程序声明变量的类型和名字。定义也是声明:当定义变量时,我们声明了它的类型和名字。

extern声明不是定义也不分配存储空间,事实上它只是说明变量定义在程序的其他地方,程序中变量可以声明多次,但只能定义一次。

如果声明有初始值,那么他可被当作是定义:

extern double pi = 3.141596;

 

● 因为常量在定义后就不能修改,所以定义时必须初始化。

const std:string hi = “hello”;

与其他变量不同,除非特别说明,在全局作用域声明的const变量是定义该对象的文件的局部变量。此变量只存在那个文件中,不能被其他文件访问。

通过指定const变量为extern,就可以在整个程序中访问const对象:

//file1.c

extern const int bufSize = 512;

//file2.c

extern const int bufSize;

非const变量默认为extern,要使const变量能够在其他文件中访问,必须要显式的指定它为extern。

 

● 引用就是对象的另一个名字,引用必须被初始化,但不能用常量来初始化,因为引用只是它绑定的对象的另一个名字,作用在引用上的所有操作事实上都是作用在该引用绑定的对象上。当引用初始化后,只要该引用存在,它就保持绑定到初始化时指向的对象,不可能将引用绑定到另一个对象。

 

● const引用是指向const对象的引用。

const int ival = 1024;

const int &refVal = ival;

int &ref2 = ival;            //error nonconst reference to a const object.

const引用可以初始化为不同类型的对象或者初始化为右值。                       const int &r = 42;

非const引用只能绑定到与该引用同类型的对象。

const引用则可以绑定到不同但相关的类型的对象或绑定到右值。

double dval = 3.14;

const int &ri = dval;     ==>

int temp = dval;

const int &ri = temp;           

如果不是const的话,那么我们会发现dval的值并没有改变,改变的只是temp的值。

 

● 枚举成员值可以是不唯一的。

enum Points{point2d = 2, point2w, point3d = 3, point3w};

枚举类型的对象的初始化或赋值,只能通过其枚举成员或同一枚举类型的其他对象来进行。

 

● 如果使用class关键字来定义类,那么定义在第一个访问标号前的任何成员都隐式指定为private;如果使用struct关键字,那么这些成员都是public。使用class还是struct关键字来定义类,仅仅影响默认的初始访问级别。

 

● 头文件用于声明而不是用于定义,当设计头文件时,记住定义和声明的区别是很重要的。定义只可以出现一次,而声明则可以出现很多次。下列语句是一些定义,所以不应该放在头文件。

extern int ival = 10;

double fica_rate;

同一个程序中有两个以上文件有上述任一个定义都会导致多重定义链接错误。因为头文件包含在多个源文件中,所以不应该含有变量或函数的定义。

 

● 一些const对象定义在头文件中,因为const对象默认为定义它的文件的局部变量,所以把它们的定义放在头文件时合法的。

如果const变量不是用常量表达式初始化,那么它就不应该在头文件中定义。相反,和其他的变量一样,该const变量应该在一个源文件中定义并初始化。应在头文件中为它添加extern声明,以使其能被多个文件共享。

 

● 避免多重包含

#ifndef SALESITEM_H

#define SALESITEM_H

 

#endif

 

● using namespace::name;

一旦使用了using声明,我们就可以直接引用名字,而不需要再引用该名字的命名空间。

 

● string类型:

string  s1;

string s2(s1);

string s3(“value”);

string s4(n,’c’);

 

string对象的操作:

s.empty();

s.size();

s[n]

s1 + s2,s1 = s2

v1 == v2

!=,<,<=,>,>=

 

string::size_type类型(unsigned):

与机器无关,任何储存string的size操作结果的变量必须为string::size_type类型,特别重要的是,不要把size的返回值赋给一个int变量。

 

当进行string对象和字符串字面值混合连接操作时,+操作符的左右操作数必须至少有一个是string类型的:

string s0 = “hello”;

string s1 = “hello” + “,”;              //error:no string operand

string s2 = s0 + “,” + “world”;    //ok   s0 + “,”  返回的是一个新的string对象。

string s3 = “hello” + “,” + s0;   //error

 

string类型通过下标操作符([])来访问string对象中的单个字符。下标操作符需要取一个size_type类型的值,来标明要访问的位置。

下标操作可用作左值,str[index] = ‘*’;

 

string对象中字符的处理:

    isalnum(c)        如果C是字母或数字,则为True。

    isalpha(c)        如果C是字母,则为True。

    iscntrl(c)          如果C是控制字符,则为True。

    isdigit(c)          如果C是数字,则为True。

    isgraph(c)        如果C不是空格,但可以打印,则为True。

    islower(c)        如果C是小写字母,则为True。

    isprint(c)         如果C是可以打印的字符,则为True。

    ispunct(c)       如果C是标点符号,则为True。

    isspace(c)      如果C是空白符,则为True。

    isupper(c)      如果C是大写字母,则为True。

    isxdigigt(c)     如果C是十六进制数,则为True。

    tolower(c)      如果C是大写字符,则返回其小写字母形式,否则直接返回C。

    toupper(c)      如果C是小写字符,则返回其大写字母形式,否则直接返回C

 

● vector类型:

vector不是一种数据类型,而只是一个类模板,可用来定义任意多种数据类型。vector类型的每一种都指定了其保存元素的类型。因此,vector<int>和vector<string>都是数据类型。

 

vector<T> v1;

vector<T> v2(v1);

vector<T> v3(n,i);

vector<T> v4(n);

 

由于vector元素连续,可能希望最好是预先分配适合的空间。但事实上,为了达到连续性,C++的做法恰恰相反。

虽然可以对给定元素个数的vector对象预先分配内存,但更有效的方法是先初始化一个空的vector对象,然后再动态地增加元素。

 

vector对象的操作:

v.empty()

v.size()

v.push_back(t)       //在v的末尾增加一个值为t的元素

v[n]、v1 = v2、v1 == v2、!=、<、<=、>、>=

 

使用size_type类型时,必须指出该类型是在哪里定义的。

vector<int>::size_type   //ok           vector::size_type     //error

 

vector下标操作的结果仍为左值。

 

for(vector<int>::size_type index = 0; index != ivec.size(); ++index)

C++程序猿在判断for循环的条件的时候,习惯于优先用!=而不是<来编写循环判断条件。

同样因为vector是动态增加的,所以我们在获取size的时候,没有在for循环之前调用size成员函数并保存其返回值,而是在for语句头中调用size成员函数。

 

迭代器:

vector<int>::iterator iter;

iter = ivec.begin();          //这时iter指向第一个元素即ivec[0]

iter = ivec.end();            //这时iter指向最后一个元素的下一个位置

迭代器类型可使用解引用操作符来访问迭代器所指向的元素。

*iter++ = 0;

for(vector<int>::iterator iter = ivec.begin(); iter != end(); ++iter)

           *iter = 0;

 

const_iterator:

每种容器类型还定义了一种名为const_iterator的类型,该类型智能用于读取容器内元素,但不能改变其值。

使用const_iterator类型时,我们可以得到一个迭代器,它自身的值可以改变,但不能用来改变其所指向的元素的值。可以对迭代器进行自增以及使用解引用操作符来读取值,但不能对该元素值赋值。不要把const_iterator对象与const的iterator对象混淆起来。声明一个const迭代器时,必须初始化迭代器。一旦被初始化后,就不能改变它的值。

任何改变vector长度的操作都会使已存在的迭代器失效。例如,在调用push_back之后,就不能再信赖指向vector的迭代器的值了。

 

● bitset类型

bitset<n> b;

bitset<n> b(u);    //b是unsigned long型u的一个副本

bitset<n> b(s);    //b是string对象s中含有的位串的副本

bitset<n> b(s,pos,n);   //b是s中从位置pos开始的n个位的副本

 

bitset<16> bitvec(0xffff);             //bit 0~15 are set to 1

 

string strval(“1100”);

bitset<32> bitvec(strval);

当用string对象初始化bitset对象时,string对象直接表示为位模式。从string对象读入位集的顺序是从右向左。

string对象的最右边字符用来初始化bitset对象的低阶位。

 

bitset对象上的操作:image

 

好了,先到这里,下篇继续。

 

BY:AloneMonkey

本文链接:http://www.alonemonkey.com/cplus-review-one.html