cpp

bilibili 侯捷 侯捷C++手把手教学(上),适合新手 侯捷手把手教学C++(下)已补充完毕

Modern C++ Tutorial: C++11/14/17/20 On the Fly

C++设计模式

基本语法

数据类型

Type categorySigned typesUnsigned types
TypeMinimum valueMaximum valueTypeMinimum valueMaximum value
Exact widthint_n__tINT_n__MININT_n__MAXuint_n__t0UINT_n__MAX
Least widthint_least_n__tINT_LEAST_n__MININT_LEAST_n__MAXuint_least_n__t0UINT_LEAST_n__MAX
Fastestint_fast_n__tINT_FAST_n__MININT_FAST_n__MAXuint_fast_n__t0UINT_FAST_n__MAX
Pointerintptr_tINTPTR_MININTPTR_MAXuintptr_t0UINTPTR_MAX
Maximum widthintmax_tINTMAX_MININTMAX_MAXuintmax_t0UINTMAX_MAX

#define

  • 使用#define时如果后面值包含运算,加括号,否则编译后可能出现问题,如 #define foo (1+1)而不是#define foo 1+1

ifdef与条件

  • 示例
#if defined(A) || defined(B)
//your define
#endif

指针所指向的数组的大小

  • 首先需要明确sizeof()是操作符不是函数
  • 函数通过指针传入数组时,应当同时将数组大小通过另外一个参数传入,如
    #include <iostream>
    #define ARRAY_LEN(a)  (sizeof(a)/sizeof((a)[0]))
     
    int b[] = {1,2,3};
    void foo(int *intArray, int size){
        std::cout << sizeof(intArray) << std::endl;
        std::cout << size << std::endl;
    }
     
    //调用函数
    int main(){
        foo(b, ARRAY_LEN(b));
    }
    输出分别为8(地址宽度为64位)和3
  • 如果在函数内对传入的指针使用sizeof(),得到的实际上指针的大小?
  • 与引用传递的对比,注意传引用调用时要给出大小
    #include <iostream>
    #define ARRAY_LEN(a)  (sizeof(a)/sizeof((a)[0]))
     
    int b[] = {1,2,3};
    void foo(int (&intArray)[3], int size){
        std::cout << sizeof(intArray)/sizeof(int) << std::endl;
        std::cout << size << std::endl;
    }
     
    //调用函数
    int main(){
        foo(b, ARRAY_LEN(b));
    }
    此时输出为3(注意除以了单个元素的大小)和3

侯捷C++手把手教学

头文件与类的声明

  • 防卫式声明

构造函数

创建一个数组,数组中元素为使用构造函数进行实例化的类对象

  • 方法一:静态数组的初始化
#include <iostream>  
using namespace  std;  
 
class foo{
public:
    int val;
	foo(int val_init);
};
 
foo::foo(int val_init) {
    val = val_init;
}
 
int main()  
{  
    foo array[] = {foo(1), foo(2), foo(3)};
    for (int i=0; i < 3; i++){
        std::cout << array[i].val << ", ";
    }
	return 0;  
}
  • 方法二:使用vector
#include <iostream>  
using namespace  std;  
#include <vector>
 
class foo{
public:
    int val;
    foo(int val_init);
};
 
foo::foo(int val_init) {
    val = val_init;
}
 
int main()  
{  
    vector<foo> array;
    for (int i=0; i < 3; i++){
        array.push_back(foo(i));
    }
    for (int i=0; i < 3; i++){
        std::cout << array[i].val << ", ";
    }
    return 0;  
}
  • 方法三,使用operator new(需要析构函数):
#include <iostream>  
using namespace  std;
 
class foo{
public:
    int val;
	foo(int val_init);
	~foo();
};
 
foo::foo(int val_init) {
    val = val_init;
}
foo::~foo(){}
 
int main()  
{  
    foo *ptr = reinterpret_cast<foo *>(::operator new(sizeof(foo)*3));
    for (int i=0; i < 3; i++){
        new(&ptr[i]) foo(i);
    }
    for (int i=0; i < 3; i++){
        std::cout << ptr[i].val << ", ";
    }
    for (int i=0; i < 3 ; i++){
        ptr[i].~foo();
    }
    delete ptr;
	return 0;  
}

参数传递与返回值

  • 如何写出大气的代码
    1. 数据一定放在private
    2. 参数尽可能是reference来传。要不要加const,看状况
    3. 返回值也尽量以reference来传
    4. 类的本体中的函数,应该加const的就要加。如果不加,使用时可能会报错
    5. 构造函数要尽量用initialization list(单冒号的那一行)

Vector与动态数组

模板

规范

魔法运算与绘图(一切都是Python的错)

  • numcpp NumCpp: A Templatized Header Only C++ Implementation of the Python NumPy Library
  • matplotplusplus Matplot++: A C++ Graphics Library for Data Visualization

多线程(C++11)

原子变量

#include <iostream>
#include <thread>
#include <chrono>
#include <atomic>
 
void func1(std::atomic<int>* val)
{
    while(true)
    {
        std::cout << "t1: " << *val << std::endl;
        std::this_thread::sleep_for(std::chrono::seconds(2));
    }
}
 
void func2(std::atomic<int>* val)
{
    int input = 0;
    while(true)
    {
        std::cout << "wait for input" << std::endl;
        std::cin >> input;
        (*val) = input;
        std::this_thread::sleep_for(std::chrono::seconds(1));
    }
}
 
int main()
{
    std::cout << "hello world\n";
 
    std::atomic<int> shared;
    shared = 0;
    std::thread t1(func1, &shared);
    std::thread t2(func2, &shared);
 
    t1.join();
    t2.join();
 
    std::cout << "end thread\n";
 
    return 0;
}

格式化打印

  • 指定输出时小数点后位数
    #include <iomanip>
     
    out_file << std::setiosflags(std::ios::fixed) << std::setprecision(2);