C++ Tips
- 自定义class,存在析构函数,那么需要同时定义或者删除拷贝构造函数和拷贝赋值函数。原因是,在拷贝构造或者拷贝复制的过程中,为浅拷贝,当程序结束,析构函数介入时,可能存在析构两次的情况。
右值,int &&可以自动转换为int const &。
__restrict关键字,告诉编译器,指针不存在重叠的情况,编译器可以进行优化,所有的非const指针都可以加上__restrict关键字,如:int * __restrict a。对于vector容器,__restrict关键字不生效,可以尝试#pragma omp simd或者#pragma GCC ivdep
关于malloc和new
1
2
3int *a = new int[102400];
int *a = (int *)malloc(102400 * sizeof(int));以上申请内存的两种语句,在实际生产环境,执行时并不会真正的分配内存,而是将这一段内存标记为不可用,即:invalid。待需要用到a数组:赋值或者其他操作时,会触发缺页中断,page fault。此时进入内核,查询此段内存是否之前malloc过,如果查询到,那么内存标记为可用,此时程序正常运行,如果未查询到malloc记录,那么触发段错误,segmentation fault。
以上两种申请内存的语句,不会进行置零操作,初始化数组时,内存被写入,此时操作系统才进行实际的内存分配,因此测试两次内存赋值操作会发现时间不同。对于new操作符有一个简便方法
1
int *a = new int[102400]{};
常见的自定义String类中,无参数构造函数也可以进行以下简单的定义:注意new char[1]后面的一对大括号
1
String::String() : m_length{0}, m_string{new char[1]{}}{}
原子操作
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17type __sync_fetch_and_add (type *ptr, type value, ...) // 将value加到*ptr上,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_sub (type *ptr, type value, ...) // 从*ptr减去value,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_or (type *ptr, type value, ...) // 将*ptr与value相或,结果更新到*ptr, 并返回操作之前*ptr的值
type __sync_fetch_and_and (type *ptr, type value, ...) // 将*ptr与value相与,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_xor (type *ptr, type value, ...) // 将*ptr与value异或,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_fetch_and_nand (type *ptr, type value, ...) // 将*ptr取反后,与value相与,结果更新到*ptr,并返回操作之前*ptr的值
type __sync_add_and_fetch (type *ptr, type value, ...) // 将value加到*ptr上,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_sub_and_fetch (type *ptr, type value, ...) // 从*ptr减去value,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_or_and_fetch (type *ptr, type value, ...) // 将*ptr与value相或, 结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_and_and_fetch (type *ptr, type value, ...) // 将*ptr与value相与,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_xor_and_fetch (type *ptr, type value, ...) // 将*ptr与value异或,结果更新到*ptr,并返回操作之后新*ptr的值
type __sync_nand_and_fetch (type *ptr, type value, ...) // 将*ptr取反后,与value相与,结果更新到*ptr,并返回操作之后新*ptr的值
bool __sync_bool_compare_and_swap (type *ptr, type oldval type newval, ...) // 比较*ptr与oldval的值,如果两者相等,则将newval更新到*ptr并返回true
type __sync_val_compare_and_swap (type *ptr, type oldval type newval, ...) // 比较*ptr与oldval的值,如果两者相等,则将newval更新到*ptr并返回操作之前*ptr的值
__sync_synchronize (...) // 发出完整内存栅栏,内存屏障
type __sync_lock_test_and_set (type *ptr, type value, ...) // 将value写入*ptr,对*ptr加锁,并返回操作之前*ptr的值
void __sync_lock_release (type *ptr, ...) // 将0写入到*ptr,(类似对*ptr解锁)c++11中atomic
- atomic_flag
1
2
3std::atomic_flag LOCK = ATOMIC_FLAG_INIT; // 原子布尔类型
LOCK.test_and_set(); //被设置,则返回true; 否则,返回false
LOCK.clear(); // 清除atomic_flag对象- atomic对int, char, bool等数据结构进行原子性封装
1
2
3
4
5std::atomic<int> counter(2); // 等同于counter.load(2);
int old = counter.fetch_add(2); // 等同于counter+=2; 注意:counter = counter + 1;并不是原子操作; fetch_add会返回旧值
counter.load(); // 读取,等同于std::cout << counter << std::endl;
int old = counter.exchange(3); // 交换并返回旧值,old = 2
bool equal = counter.compare_exchange_strong(old, new); // equal with old, counter = new, 返回true, 此处的old为引用,不能直接传入右值2