记录一些零散的C++笔记,同一topic的内容多了之后再整理到一起。

1. vector的初始化。

vector可以这样初始化:

vector<int> ivec{ 1,2,3 };  
vector<int> ivec2 = { 1,2,3 };  

vector也可以这样初始化:

int an_array[] = { 5,6,7,8 };
vector<int> an_vector(an_array, an_array + 4);

用已存在的数组元素来初始化vector。传给vector的an_array和an_array+4(指针作为数组的迭代器)指示把范围 [an_array,an_array+4)内的元素用来初始化an_vector。注意an_array+4中的4是数组an_array的长度,而an_array+4是超出末端迭代器。这样an_vector的元素初始化为an_array的副本。

也可以只取数组中一部分用来初始化an_vector:

int an_array[] = { 5,6,7,8 };
vector<int> an_vector(an_array + 1, an_array + 3);
//an_vector:{6,7}

则an_vector初始化得到两个元素,6和7。

可以用数组的迭代器初始化vector,当然也可以用已经存在的vector初始化vector:

vector<int> an_vector1{ 2,3,4,5,6 };
vector<int> an_vector2(an_vector1.begin(), an_vector1.end());

这样an_vector2初始化为an_vector1的一个副本。同样也可以只取an_vector1部分元素:

vector<int> an_vector1{ 2,3,4,5,6 };
vector<int> an_vector2(an_vector1.begin() + 1, an_vector1.begin() + 4);

则an_vector2={3,4,5}。

 

2. 关于set

 

3. 关于超出迭代器头和尾的问题

(使用的是Visual Studio Community 2015)

(release 和 debug 模式下结果不同)

在debug模式下:

使用vector的iterator时,若迭代器超出了iterator.begin()之前或者iterator.end()之后(包括iterator.end()这个位置)并不会出现运行问题,但是试图获取该迭代器指向的对象则会出现运行错误。

而在release模式下并不会报错出现运行错误。

 

4. 尽量用STL算法代替手写循环。

5. 利用强大的stringstream可以方便地进行数字和字符串之间的转换。

先尝试一下double到string和int到string的转换。

stringstream ss;
string doublestring("123.456"),intstring("888");
double testdouble;
int testint;
ss << doublestring;
ss >> testdouble;
ss.clear();
ss << intstring;
ss >> testint;
cout << "testdouble: " << testdouble << endl;
cout << "testint: " << testint << endl;

stringsream对象的构造和析构函数相当耗费时间,因此要提高效率的话就要减少stringstream对象的创建,尽量使用同一个stringstream对象进行转换,但是在多次转换之间记得调用clear()函数,否则转换结果会出现问题。现在如果注释掉上面代码的ss.clear()行,则出现如下结果

再来尝试一下string到double和string到int的转换。

stringstream ss;
double testdouble(456.789);
int testint(745);
string doublestring, intstring;
ss << testdouble;
ss >> doublestring;
cout << "doublestring: " << doublestring << endl;
ss.clear();
ss << testint;
ss >> intstring;
cout << "intstring: " << intstring << endl;

运行结果

同样不要忘记多次转换之间调用stringstream对象的clear()函数

当然也可以利用同一个stringstream对象进行从字符到数字和从数字到字符的转换,记得多次转换之间clear()就行了。

stringstream ss;
double testdouble(456.789);
string intstring("233");
string doublestring;
int testint;

ss << testdouble;
ss >> doublestring;
cout << "doublestring: " << doublestring << endl;
ss.clear();
ss << intstring;
ss >> testint;
cout << "testint: " << testint << endl;

结果:

 

6. 关于map

map也会对元素进行排序。默认为key的升序排列。所以用迭代器对map进行遍历是,会按照key的升序得到map的元素。

 

7. 关于string

string定义了find和rfind函数,find和rfind函数最简单的使用是用来查找某个字符在字符串中的位置。find可以返回该字符第一次出现的下标,rfind则可以返回该字符最后一次出现的下标。

string s("asd fas dfa,sfd");
int first_a = s.find('a'), final_a = s.rfind('a');
int first_d = s.find('d'), final_d = s.rfind('d');
cout << "first a: " << first_a << endl;
cout << "final a: " << final_a << endl;
cout << "first d: " << first_d << endl;
cout << "final d: " << final_d << endl;

结果:

同事string还有back(), pop_back(), empty()等很多有用的函数。要善于使用这些封装好的函数,能够很方便地解决很多问题。

 

8. map<int,pair<int,bool> >

string s("asfasarfaf");
map<char, pair<int, bool> > charmap;
for (auto c : s)
{
    ++charmap[c].first;
}

这段代码中pair会被初始化为(0,false),所以可以直接计算字符串s中各个字符的数量,而对于每个字符,pair.second也有被初始化为false。

but还是需要深究一下,这么做是不是安全的呢?