书:C++高级编程 第三版
1. using指令不要过度使用,如果使用过多,实际上就是完全取消了名称空间。
2. 切勿在头文件中使用using指令或者using声明,否则每个人都会包含你的头文件。
3. 变量声明时建议初始化;
4. auto关键字用途:
(1) auto x = 123; 用于变量
(2) auto result = getFoo(); 用于函数返回值、
(3) 替代函数;
(4) 用于通用的lambda表达式;
5. int x = 123; decltype(x) y = 456;
6. 动态分配数组
int arraySize;
cin >> arraySize;
int* data = new int[arraySize];
- C++中,避免使用malloc()和free(),而使用new和delete,或者使用new[]和delete[];每次调用new时,都应该相应地调用delete,每次调用new[]时,都应该相应地调用delete[],以避免内存泄露。
- 真正的空指针nullptr;
- 3种智能指针:
std::unique_ptr; std::shared_ptr; std::weak_ptr; 均定义在头文件中;unique_ptr只属于它指向的对象,在超出作用或被删除时,会自动释放内存或资源; - const引用参数的主要价值在于效率。当向函数 传递值时,会制作一个完整的副本。当传递引用时,实际上只是传递了一个指向原始数据的指针,这样计算机就不需要执着副本。通过传递const引用,可以做到二者兼顾——不需要副本,原始变量也不需要修改。在处理对象时,const引用会变得更加重要,因为对象可能比较庞大,复制对象可能需要很大的代价。
- 最好将不改变对象的任何数据成员的成员函数声明为const。(const-correctness原则)
- vector基本功能和迭代器
#include<string>
#include<vector>
#include<iostream>
#include<iterator>
using namespace std;
int main()
{
vector<string> myVector = {"A first string", "A second string"};
myVector.push_back("A third string");
myVector.push_back("The last string in the vector");
cout << "第一种遍历方式:\n";
for (const auto& str : myVector)
cout << str << endl;
cout << "第二种遍历方式:\n";
for (string& str : myVector)
cout << str << endl;
cout << "第三种遍历方式:\n";
for (auto iterator = cbegin(myVector); iterator != cend(myVector); ++iterator)
{
cout << *iterator << endl;
}
system("pause");
return 0;
}
- 求字符串长度strlen(“A first string”)
- 数值转换为字符串:to_string(参数)
long double d = 3.14L;
string s = to_string(d);
- 字符串转为数值
int stoi(const string& str,size_t *idx=0, int base=10)
long stol(const string& str, size_t *idx=0, int base=10)
unsigned long stoul(const string&str, size_t *idx=0, int base=10)
long long stoll(const string& str, size_t *idx=0, int base=10)
unsigned long long stoull(const string& str, size_t *idx=0, int base=10)
float stof(const string& str, size_t *idx=0)
double stod(const string& str,size_t *idx=0)
long double stold(const string& str,size_t *idx=0)
//eg:
const string s = "1234";
int i = stoi(s);
- 调用复制构造函数
无论什么时候给函数或者方法传递一个对象,编译器都会调用新对象的复制构造函数进行初始化。
当函数或者方法返回对象时,也会调用复制构造函数。此时,编译器使用复制构造函数创建一个临时的、没有名称的对象。可将传递的参数作为const引用,从而避免调用复制构造函数的开销。
显式调用复制构造函数:
SpreadsheetCell myCell2(4);
SpreadsheetCell myCell3(myCell2);
当向函数或者方法传递对象时,为了避免复制对象,可以让函数或者方法采用对象的引用做参数。按引用传递对象通常比按值传递对象的效率更高,因为只需要复制对象的地址,而不需要复制对象的全部内容。,此外,按引用传递可以避免对象动态内存分配的问题。如果不想修改对象,可以添加const。
最好按const引用传递而不是按值传递对象。
复制构造函数在下列情况下使用:
(1) 根据另一个同类型的对象显示或隐式初始化一个对象;
(2) 复制一个对象,将它作为实参传给一个函数;
(3) 从函数返回时复制一个对象;
(4) 初始化顺序容器中的元素;
(5) 根据元素初始化式列表初始化数组元素;
17. 求最大公约数和最小公倍数
#include <iostream>
#include <string>
int main()
{
int i, j;
cin >> i >> j;
int temp;
if (i < j)
{
temp = j;
j = i;
i = temp;
}
int amass = i * j;
while (j != 0)
{
temp = i%j;
i = j;
j = temp;
}
cout << "最大公约数:" << to_string(i) << endl;
cout << "最小公倍数: " << to_string(amass / i) << endl;
system("pause");
return 0;
}
- 流类型不能作为函数的形参或返回类型,必须使用流类型的指针或引用。
//正确
ostream& print(ostream& os);
//错误
ostream print(ostream os);
- 对于open_file函数,在调用open前先调用clear函数。如果程序执行close函数失败,则不能用文件流in打开给定的文件。
例子:
ifstream& open_file(ifstream &in, const string &file)
{
//关闭以防它已经打开
in.close();
//清除内部状态
in.clear();
//打开给定文件
in.open(file.c_str());
return in;
}
- 不可以使用容器来存储iostream,因为容器元素类型必须支持赋值操作及复制,而iostream类型不支持赋值和复制。
- 使用循环将list容器的元素逆序输出:
list<int> lst1;
list<int>::iterator iter1 = lst1.begin(),iter2 = lst1.end();
while(iter2!=iter1)
cout << *(--iter2);