C++

volatile

变量如果加了 volatile 修饰,则会从内存重新装载内容,而不是直接从寄存器拷贝内

重载运算符

  1. 一般情况下,单目运算符最好重载为类的成员函数;双目运算符则最好重载为类的友元函数。
  2. 以下一些双目运算符不能重载为类的友元函数:=、()、[]、->。
  3. 类型转换函数只能定义为一个类的成员函数而不能定义为类的友元函数。
  4. 若一个运算符的操作需要修改对象的状态,选择重载为成员函数较好。
  5. 若运算符所需的操作数(尤其是第一个操作数)希望有隐式类型转换,则只能选用友元函数。
  6. 当运算符函数是一个成员函数时,最左边的操作数(或者只有最左边的操作数)必须是运算符类的一 个类对象(或者是对该类对象的引用)。如果左边的操作数必须是一个不同类的对象,或者是一个内部 类型的对象,该运算符函数必须作为一个友元函数来实现。
  7. 当需要重载运算符具有可交换性时,选择重载为友元函数。

static关键字

static关键字的使用
静态局部变量:作用域在声明它的这个函数中,只会被初始化一次。

普通全局变量:在本文件内可以被无限制地使用。而且其他的源文件中,也可以通过extern关键字引用后使用。

静态全局变量:在普通全局的基础上取消了extern关键字的引用,即无论怎么样,只能给本文件的程序使用,其他文件不能使用。(保护代码模块化,封闭外部接口)。

静态成员变量在类中先做引用声明,再做定义性说明。

c++ socket编程

c++ socket编程

初始化和赋值要注意区分

protected:受保护的成员对于派生类的成员和友元来说是可访问的,而private基类成员对于派生类成员和友元是不能访问的

“malloc在堆上分配的内存块,使用free释放内存,而new所申请的内存则是在自由存储区上,使用delete来释放。”

C++中字符串常量为了兼容C 可以赋值给char*类型

size_t

size_t:适当地使用size_t还会使你的代码变得如同自带文档。当你看到一个对象声明为size_t类型,你马上就知道它代表字节大小或数组索引,而不是错误代码或者是一个普通的算术值

size_t是一些C/C++标准在stddef.h中定义的。这个类型足以用来表示对象的大小。
size_t的真实类型与操作系统有关,在32位架构中被普遍定义为:

typedef   unsigned int size_t;

而在64位架构中被定义为:

typedef  unsigned long size_t;

size_t在32位架构上是4字节,在64位架构上是8字节,在不同架构上进行编译时需要注意这个问题。
而int在不同架构下都是4字节,与size_t不同;且int为带符号数,size_t为无符号数。

Const成员函数

普通对象可以调用const成员函数,而const对象可以不能调用非const成员函数(const对象必须有专供的函数)。
const函数的使用与分析

在早期某些编译器会将C++代码翻译为C代码,然后使用C编译器生成可执行文件。其中翻译的一个转化就是:将this指针显式添加到成员函数的第一个参数位置上,并在成员函数调用时,自动将对象的地址传递给参数this。

//原型转换为C代码后的样子
void bark(const Dog*this);
void feed(Dog*this,unsigned add);

//调用时的转换
dog.feed(2);   ----->  feed(&dog , 2); 
dog.bark();    ----->  bark(&dog);

当然实际编译器不会是这么工作的,这只是帮助理解代码运作的一种方式。

const关键字

指向常量的指针(pointer to const)只能保证不通过这个指针来改变所指向的地址的内容。

无论是对常量的引用(reference to const)还是指向常量的指针(pointer to const)都是他们的一厢情愿觉得自己指向了一个常量,而不去修改它。
常量指针(const pointer)只能保证指针本身不会被改变,而指向的值是否变化就不得而知了。

new与delete

C++标准规定:delete空指针是合法的,没有副作用。

所以我们在Delete指针后赋值为NULL或0是个好习惯。对一个非空指针delete后,若没有赋NULL,若再次delete的话,就回指向一个不可访问的空间.

namespace

只在cpp文件中使用namespace,不要在头文件中使用。

容器

向一个vector、string或deque插入元素会使所有指向容器的迭代器、引用和指针失效。
因为不同容器使用不同的策略来分配元素空间,在vector或string尾部以外、deque首尾之外的位置插入会引起整个对象的存储空间的重新分配。

nullptr,0,NULL

整数用 0, 实数用 0.0, 指针用 nullptr 或 NULL, 字符 (串) 用 '\0'.

整数用 0, 实数用 0.0, 这一点是毫无争议的.

对于指针 (地址值), 到底是用 0, NULL 还是 nullptr. C++11 项目用 nullptr; C++03 项目则用 NULL, 毕竟它看起来像指针。实际上,一些 C++ 编译器对 NULL 的定义比较特殊,可以输出有用的警告,特别是 sizeof(NULL) 就和 sizeof(0) 不一样。

字符 (串) 用 '\0', 不仅类型正确而且可读性好.

编码

ASCII显示中文是用的多字节编码,用多个字节来表示中文;UNICODE两个字节一个字符号。

输出参数和返回值

out prameter:当函数内部不需要做创建操作的时候使用
return value:当函数内部需要创建时使用,注意内存管理 #TODO:考虑智能指针是否可以做函数内创建对象的内存管理

C++在new时的初始化的规律可能为:对于有构造函数的类,不论有没有括号,都用构造函数进行初始化;如果没有构造函数,则不加括号的new只分配内存空间,不进行内存的初始化,而加了括号的new会在分配内存的同时初始化为0

范围for (range for statement)

for (declaration : expression)
    statement

若要改变容器内的数据,需要使用引用for(auto &i : v)
范围for等价于

for (auto beg = v.begin(), end = v.end() ; beg != end; ++beg) {
    auto &r = *beg;
    r *= 2;
}

mutable 关键字

const意思是“这个函数不修改对象内部状态”。为了保证这一点,编译器也会主动替你检查,确保你没有修改对象成员变量——否则内部状态就变了。
mutable意思是“这个成员变量不算对象内部状态”。
比如,你搞了个变量,用来统计某个对象的访问次数(比如供debug用)。它变成什么显然并不影响对象功用,但编译器并不知道:它仍然会阻止一个声明为const的函数修改这个变量。把这个计数变量声明为mutable,编译器就明白了:这个变量不算对象内部状态,修改它并不影响const语义,所以就不需要禁止const函数修改它了。
作者:invalid s
链接:https://www.zhihu.com/question/64969053/answer/226142449
来源:知乎

lambda捕获列表

  1. 没有使用任何函数对象参数。
  2. = 函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是值传递方式(相当于编译器自动为我们按值传递了所有局部变量)。
  3. & 函数体内可以使用Lambda所在作用范围内所有可见的局部变量(包括Lambda所在类的this),并且是引用传递方式(相当于编译器自动为我们按引用传递了所有局部变量)。
  4. this 函数体内可以使用Lambda所在类中的成员变量。
  5. a 将a按值进行传递。按值进行传递时,函数体内不能修改传递进来的a的拷贝,因为默认情况下函数是const的。要修改传递进来的a的拷贝,可以添加mutable修饰符。
  6. &a 将a按引用进行传递。
  7. a, &b 将a按值进行传递,b按引用进行传递。
  8. =, &a, &b 除a和b按引用进行传递外,其他参数都按值进行传递。
  9. &,a, b 除a和b按值进行传递外,其他参数都按引用进行传递。

判断平台

https://stackoverflow.com/questions/5919996/how-to-detect-reliably-mac-os-x-ios-linux-windows-in-c-preprocessor

#if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__)
   //define something for Windows (32-bit and 64-bit, this part is common)
   #ifdef _WIN64
      //define something for Windows (64-bit only)
   #else
      //define something for Windows (32-bit only)
   #endif
#elif __APPLE__
    #include 
    #if TARGET_IPHONE_SIMULATOR
         // iOS Simulator
    #elif TARGET_OS_IPHONE
        // iOS device
    #elif TARGET_OS_MAC
        // Other kinds of Mac OS
    #else
    #   error "Unknown Apple platform"
    #endif
#elif __linux__
    // linux
#elif __unix__ // all unices not caught above
    // Unix
#elif defined(_POSIX_VERSION)
    // POSIX
#else
#   error "Unknown compiler"
#endif

dll

导出类的时候最好用纯虚接口的模式;dll 接口最好不要把stl或者模板容器传来传去的。

动态库中的全局变量,在被其他进程使用时,会拷贝一份,所以多个进程使用同一个动态库中的全局变量也不会相互影响。也不会改变动态库中该变量的值。类似于fork的COW技术

如果某动态库中有一个全局变量,程序a使用的这个动态库,程序b也使用了这个动态库,那么程序a和b中的全局变量是一个吗?也就是说,进程间使用动态库时,共享全局变量吗?答题是:是一个,共享,但写时拷贝,给程序员的感觉是:不共享。

https://blog.csdn.net/frank_jb/article/details/90483206

你可能感兴趣的:(C++)