这里用来积累犯错语句,以提高自己的警觉。

使用外部函数和外部变量 -undefined reference

  1. g++ -c linkA.cpp #编译
  2. g++ -c linkB.cpp #编译
  3. g++ -o linkB linkB.o linkA.o #连接生成 linkB.exe
  4. ./linkB.exe #运行程序
  5. 如果按照我们平时的默认方式,第三行其实是 g++ -o linkB linkB.o
  6. 这时候报错:
  7. main.o: In function `main':
  8. main.c:(.text+0x7): undefined reference to `test'
  9. collect2: ld returned 1 exit status
  10. 说明是连接时缺失相关目标文件
  11. 其实一行代码解决问题:g++ -o linkB linkB.cpp linkA.cpp #连接生成 linkB.exe

错误类型

std::bad_alloc

当内存被占满,使用new无法手动分配动态内存的时候;

out_of_range

下标超界

循环

求10以内所有正奇数之和

  1. int sum = 0;
  2. for(int i = 1 ; i!= 10 ; i+=2)
  3. sum+=i;

错误在于循环中i+=2 ,当i=9时循环true,但是+2之后i=11,这时候i!=10 无法限制i增长。

cin遇到回车不停止

  1. char c;
  2. cout << "Enter the " << NUM_QUES << " question tests:" << endl;
  3. while(cin.get(c)) {
  4. if(c != '\n') {
  5. /*……*/
  6. }
  7. }

基于范围的for循环,出现需要“begin”函数的问题

可能是函数调用问题,具体机制不太明白

  1. #include <iostream>
  2. void func0( int a[3][4]){
  3. for( auto &n : a ) //此处a被识别为指针 int (*a)[4] , 提示需要begin函数
  4. std::cout<<n<<std::endl;
  5. }
  6. int main(){
  7. int a[3][4]{{2,4,23,2},
  8. {5,45},
  9. {45,23,2,4}};
  10. for(auto &n : a) //此处a被识别为数组 int a[3][4] , 编译通过 但得到的是三个指针地址
  11. std::cout<<n<<std::endl;
  12. func0(a);
  13. return 0;
  14. }

基于范围的for循环使用的要求及依赖条件

(1)for循环迭代的范围是可以确定的;如数组的第一个元素和最后一个元素便构成了for选好的迭代范围。
(2)对于用户自定义的类,若类中定义便实现的有begin、end函数,则这个begin、end便是for循环的迭代范围。
(3)基于范围的for循环要求迭代器的对象实现:++ ==等操作符。
(4)对于STL标准模板库中(如:vector,set,list,map,queue,deque,string等)的各种容器使用“基于范围的for循环”是不会有任何问题的,因为这些容器中都定义了相关操作。

小数保留与四舍五入

对一个数x做四舍五入:floor(x+0.5) //强制转int会直接丢失小数

对一个数x保留小数点后两位:floor(x*100+0.5)/100

输入输出

std::cout:

The global objectsstd::coutandstd::wcoutcontrol output to a stream buffer of implementation-defined type (derived from std::streambuf), associated with the standard C output stream stdout.

printf:

Loads the data from the given locations, converts them to character string equivalents and writes the results to a variety of sinks.

  • std::cout, std::cin 是全局对象, operator << 和 operator >> 是流运算符, std::cout 重载了 << 运算符, std::cin 重载了 >> 运算符.
  • printf 是函数.

看到上面的回答提到了二者混用问题, 说 printf 速度比 cout 要快, 这个其实是不对的. 我们看上面std::cout 解释的最后一句, std::cout 是默认与C标准输出stdout 同步的(std::cin 同理), 所以会有额外的运算. C++ 提供了 std::ios_base::sync_with_stdio 这样一个函数来设置是否同步, 但是关闭了同步之后可能会出现错误.

然而, 我们在看 cin 的说明,

Oncestd::cinis constructed, std::cin.tie() returns &std::cout, and likewise, std::wcin.tie() returns &std::wcout. This means that any formatted input operation onstd::cinforces a call to std::cout.flush() if any characters are pending for output.

cin 被预设绑定了 cout, 被绑定的 ostream 在 istream 输入会被 flush, 标准库提供了 std::cin.tie()设置绑定对象.

说到这了, 顺便说一下 std::endl 这个东西, 可以说等价于 << ‘\n’ << flush, 所做的事情就是清空缓冲区并输出到输出流. 上面说到了 std::cout 会把输出放到一个叫缓冲区(stream buffer) 里, 直到缓冲区满了才会清空缓冲区并把字串输出到 stdout 之类的输出流, 这也就是为什么关闭了缓冲区可能会出现错误. 那么说到这里也就整明白了, 如果频繁使用 std::endl 来做换行输出, 那便是破坏了 std::cout 本身的类似于优化的操作, 也就导致了通常认为 std::cout 的速度比 printf慢.

这也就很好的解释 leetcode 中经常看到的一段加速代码:

  1. static const int _ = []
  2. {
  3. ios::sync_with_stdio(false);
  4. cin.tie(nullptr);
  5. return 0;
  6. } ();

C++尽量用cin,cout;就像用vector而不是数组,string而不是char*cout是一个系统对象,重载了<<运算符,所以可以自动匹配多种数据输出,进行动态绑定

关于底层过程,cout对象的生成会开辟内存(缓冲区)用来存需要输出的数据,当遇到换行时,cout会进行换行并刷新缓冲区(输出当前缓冲区的内容)

传统觉得printf比较快,因为cout的继承体系,构造和析构上会影响效率。