c++内存模型

c++内存模型

多核时代,程序员们为了系统运行效率做了很多事情。并发、多线程是其中绕不开的一个话题,有了多线程,随之而来的就是线程之间的同步,临界区的出现,然后就是锁的使用。程序员随之发现锁的开销较大,于是有了缩短临界区话题,尽可能的让临界区变得更小一点。但是总归临界区的缩小是有限度的,也就是有天花板的。因此我们开始探索原子操作,无锁化编程。于是为了功能正常的情况下,还要保证良好的效率,本文探讨原子操作的背后,内存的组织形式,编译器、cpu 的执行顺序,语言为 c++ 语言。

一、内存模型的由来

c++11 标准提出了内存模型,而在 c++11 之前,c++ 本身没有多线程的概念,c++ 使用者使用的是操作系统为我们提供的多线程、原子操作。那时的编译器和处理器认为系统中只有一个执行流。但在多线程之后,编码变难了,开发者编写的代码和最终运行的代码之间往往存在较大的差异,而运行的结果与开发者预期的一致,只是表现而已。

那么产生差异的原因主要来自于如下三个方面:

  • 编译器的优化
查看更多

数据语意

本文测试代码的环境为:x86-64,ubuntu22.04,gcc7.5.0

一、缘起

先使用一段代码引入本文所要探讨的主题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class X {};
class Y : public virtual X {};
class Z : public virtual X {};
class A : public Y, public Z {};

int main() {
std::cout << "sizeof X: " << sizeof(X) << std::endl;
std::cout << "sizeof Y: " << sizeof(Y) << std::endl;
std::cout << "sizeof Z: " << sizeof(Z) << std::endl;
std::cout << "sizeof A: " << sizeof(A) << std::endl;

X x1, x2;
std::cout << &x1 << " " << &x2 << std::endl;

Y y1, y2;
std::cout << &y1 << " " << &y2 << std::endl;

Z z1, z2;
std::cout << &z1 << " " << &z2 << std::endl;

A a1, a2;
std::cout << &a1 << " " << &a2 << std::endl;
return 0;
}

# g++ main.cpp -g -o main
# ./main
sizeof X: 1
sizeof Y: 8
sizeof Z: 8
sizeof A: 16
0x7fffb23046fe 0x7fffb23046ff
0x7fffb2304700 0x7fffb2304708
0x7fffb2304710 0x7fffb2304718
0x7fffb2304720 0x7fffb2304730

如上的代码也是虚继承解决菱形继承中命名冲突和冗数据的问题。虚继承的目的是让某个类做出声明,承诺愿意共享他的基类。这个被共享的基类就称为虚基类。

查看更多

c++常用技巧

一、数据交换格式

1. JSON

json 格式方便易用,性能一般。纯文本,容易阅读,方便编辑,适用性最广

推荐库实现:https://github.com/nlohmann/json。功能完善、使用方便

2. MessagePack

二进制格式。性能比 JSON 好。比如 redis 就使用它。小巧高效,在开源界接受程度比较高

官网:https://msgpack.org/

3. protobuf

二进制数据格式,工业级产品。是工业级的数据格式,注重安全和性能,多用在大公司的商业产品里

查看更多

c++语言特性

一、关键字 auto / decltype / const / volatile / mutable

  • 自动类型推导:auto 和 decltype。“自动类型推导”是给编译器下的指令,让编译器去计算表达式的类型。

  • const 与 volatile,如下代码

    1
    2
    3
    4
    5
    6
    // 需要加上volatile修饰,运行时才能看到效果
    const volatile int MAX_LEN = 1024;

    auto ptr = (int*)(&MAX_LEN);
    *ptr = 2048;
    cout << MAX_LEN << endl; // 输出2048

查看更多