首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >C++ 中文周刊 2025-02-09 第178期

C++ 中文周刊 2025-02-09 第178期

作者头像
王很水
发布2025-02-18 21:04:33
发布2025-02-18 21:04:33
9800
代码可运行
举报
运行总次数:0
代码可运行

文章

shared_ptr overuse in C++

https://www.tonni.nl/blog/shared-ptr-overuse-cpp

省流 不共享不要滥用

Falsehoods programmers believe about null pointers

https://purplesyringa.moe/blog/falsehoods-programmers-believe-about-null-pointers/

列举一些对空指针的误解,比如访问空指针会挂,c/c++语言设定如此,其他语言会捕获异常特殊处理

额我觉得还是不要知道的好

C++26: erroneous behaviour

https://www.sandordargo.com/blog/2025/02/05/cpp26-erroneous-behaviour

c++的未定义行为涉及的面太广,有必要收敛一些场景,比如没有初始化读就读这种场景,归纳为EB

如果真的需要这种行为,主动标记[[indeterminiate]] 这种标记下没初始化就使用才被归纳为UB

比如

代码语言:javascript
代码运行次数:0
运行
复制
void foo() {
  int d [[indeterminate]];  // d has an indeterminate value
  bar(d); // that's undefined behaviour!
}

不过目前为止只是提案 P2795,没有编译器支持实现

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2024/p2795r5.html

Thread-safe memory copy

https://lemire.me/blog/2025/02/07/thread-safe-memory-copy/

代码鉴赏 安全的memcpy

https://github.com/v8/v8/blob/9e5d8118e2af44b94515db813f5a0aecd8149b7a/src/base/atomicops.h#L363

代码语言:javascript
代码运行次数:0
运行
复制
inline void Relaxed_Memcpy(volatile Atomic8* dst, volatile const Atomic8* src,
                           size_t bytes) {
constexprsize_t kAtomicWordSize = sizeof(AtomicWord);
while (bytes > 0 &&
         !IsAligned(reinterpret_cast<uintptr_t>(dst), kAtomicWordSize)) {
    Relaxed_Store(dst++, Relaxed_Load(src++));
    --bytes;
  }
if (IsAligned(reinterpret_cast<uintptr_t>(src), kAtomicWordSize) &&
      IsAligned(reinterpret_cast<uintptr_t>(dst), kAtomicWordSize)) {
    while (bytes >= kAtomicWordSize) {
      Relaxed_Store(
          reinterpret_cast<volatile AtomicWord*>(dst),
          Relaxed_Load(reinterpret_cast<constvolatile AtomicWord*>(src)));
      dst += kAtomicWordSize;
      src += kAtomicWordSize;
      bytes -= kAtomicWordSize;
    }
  }
while (bytes > 0) {
    Relaxed_Store(dst++, Relaxed_Load(src++));
    --bytes;
  }
}

每个byte都原子store load 线程安全了

对于V8来说,安全比较重要。即使这玩意慢三四十倍

Richard Szabo - Traps with Smart Pointers (Lightning Talk)

省流 shared ptr一律使用make_shared构造

使用alias 构造 搭配weak ptr使用存在问题

如何避免类只能通过make_shared构造?构造函数tag + 静态函数匹配。看嗲吗

代码语言:javascript
代码运行次数:0
运行
复制
class A: std::enable_shared_from_this<A> {
private:
struct Private {};
public:
  A(Private dummy, int member) : member_(member) {}
template <typename... ArgsT>
static std::shared_ptr<A> create(ArgsT&&... args) {
    returnstd::make_shared<A>(Private(), std::forward<ArgsT>(args)...);
  }
private:
int member_ = 1;
};

int main() {
std::cout << "The Start\n\n";
auto a_sptr = A::create(42);
std::cout << std::endl << "The End!";
return0;
}

Data Storage in Entity Component Systems

https://docs.google.com/presentation/d/1PbCH2IRg8lW08JlUz-xQEQjTo_Fr5n9QZOTEjGqZnuU/edit#slide=id.g1e93a5b7c98_0_172

介绍数据局部性有利的数据结构 Dense/Sparse Array

简单说就是这个德行

代码语言:javascript
代码运行次数:0
运行
复制
#include <vector>
#include <cassert>

template<typename T>
class DenseSparseArray {
public:
    // 插入元素(假设 entity 是唯一标识)
    void insert(uint32_t entity, const T& value) {
        if (entity >= sparse.size()) {
            sparse.resize(entity + 1, -1); // -1 表示无效索引
        }
        
        if (sparse[entity] == -1) {
            sparse[entity] = dense.size();
            dense.push_back({entity, value});
        }
    }

    // 删除元素
    void erase(uint32_t entity) {
        if (contains(entity)) {
            size_t dense_idx = sparse[entity];
            auto& last = dense.back();

            // 将要删除的元素与最后一个元素交换
            std::swap(dense[dense_idx], last);
            sparse[last.entity] = dense_idx;

            dense.pop_back();
            sparse[entity] = -1;
        }
    }

    // 访问元素
    T& operator[](uint32_t entity) {
        assert(contains(entity));
        return dense[sparse[entity]].value;
    }

    // 判断是否存在
    bool contains(uint32_t entity) const {
        return entity < sparse.size() && sparse[entity] != -1;
    }

    // 迭代器支持
    auto begin() { return dense.begin(); }
    auto end() { return dense.end(); }

private:
    struct Element {
        uint32_t entity;
        T value;
    };

    std::vector<int> sparse;  // 稀疏数组(存储索引)
    std::vector<Element> dense; // 密集数组(实际数据)
};

enseSparseArray<int> arr;

arr.insert(100, 42);  // 插入 entity=100
arr.insert(200, 77);  // 插入 entity=200

std::cout << arr[100]; // 输出 42

arr.erase(100);       // 删除 entity=100

for (auto& elem : arr) { // 遍历所有有效元素
    std::cout << elem.entity << ": " << elem.value << "\n";
}

deepseek帮我写的

这种玩法比较方便遍历且不失访问速度,对于小数据集是非常有用的

另外PPT里还提到了一些优化。感兴趣可以看EnTT代码

https://github.com/skypjack/entt

Optimizing Mulithreading Performance

https://meetingcpp.com/mcpp/slides/2023/Mulithreading_performance735913.pdf

简单介绍MESI那套东西,多线程 cache局部性非常重要,另外介绍一些影响性能的场景

  1. 数据竞争,比如atomic fetch add
  2. 数据局部性影响,多个线程访问一份数据
  3. 线程过多,上下文切换开销重
  4. False Sharing,不同数据在同一块cacheline造成互相干扰
    1. 线程数组,每个线程访问数组的一个元素,没padding大概率互相干扰
    2. 类似,矩阵计算分块,分的不够开导致互相干扰
    3. 结构体字端访问,没有pading导致互相干扰
    4. 动态分配的小对象,存在可能
    5. 分配大内存专属使用
    6. 尽可能对齐
    7. 使用std::harware_destructive_interference_size alignas
    8. 典型场景

Class layout

https://meetingcpp.com/mcpp/slides/2023/Class%20Layout%20-%20meeting%20c++271911.pdf

比较常规

介绍了基本的字段大小,继承影响,对齐影响,EBO,no_unique_address, 以及分析工具

代码语言:javascript
代码运行次数:0
运行
复制
clang++ -cc1 -fdump-record-layouts # (or -Xclang -fdump-record-layouts)
g++ -fdump-lang-class (or -fdump-class-hierarchy) # (dumps to a file, so not usable in Compiler explorer)
msvc /d1reportAllClassLayout
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-02-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CPP每周推送 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • shared_ptr overuse in C++
  • Falsehoods programmers believe about null pointers
  • C++26: erroneous behaviour
  • Thread-safe memory copy
  • 代码鉴赏 安全的memcpy
  • Richard Szabo - Traps with Smart Pointers (Lightning Talk)
  • Data Storage in Entity Component Systems
  • Optimizing Mulithreading Performance
  • Class layout
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档