相关疑难解决方法(0)

何时使用reinterpret_cast?

我对reinterpret_castvs 的适用性感到困惑static_cast.从我读到的一般规则是使用静态转换,当类型可以在编译时解释,因此这个词static.这是C++编译器内部用于隐式转换的转换.

reinterpret_casts适用于两种情况,将整数类型转换为指针类型,反之亦然,或将一种指针类型转换为另一种指针类型.我得到的一般想法是不可移植的,应该避免.

我有点困惑的地方是我需要的一种用法,我从C调用C++并且C代码需要保持C++对象,所以基本上它拥有一个void*.什么演员应该用于在void *类型和类型之间进行转换?

我看过两者的用法static_castreinterpret_cast?虽然从我读过的内容看起来似乎static更好,因为演员阵容可以在编译时发生?虽然它说用于reinterpret_cast从一种指针类型转换为另一种指针类型?

c++ casting

432
推荐指数
6
解决办法
31万
查看次数

C++ POD结构继承?是否有关于派生成员的内存布局的保证

比方说,我有一个struct RGB,我想创建struct RGBA,继承RGB:

struct RGB {
    unsigned char r;
    unsigned char g;
    unsigned char b;
};

struct RGBA: RGB {
    unsigned char a;
};
Run Code Online (Sandbox Code Playgroud)

两者都将用于读取未压缩的图像数据:

RGBA *pixel=static_cast<RGBA *>(image->uncompressed_data);
Run Code Online (Sandbox Code Playgroud)

问题:关于内存布局,这样安全struct RGBA吗?有人保证:

  • unsigned char a之后RGB struct(不是之前)
  • 之间没有填充struct RGB和参数来自struct RGBA

会有#pragma pack帮助吗?这都是关于继承期间的内存布局.

c++ inheritance pod

25
推荐指数
2
解决办法
5437
查看次数

高效的类型双关,没有未定义的行为

假设我正在开发一个名为 libModern 的库。该库使用称为 libLegacy 的遗留 C 库作为实现策略。libLegacy 的界面如下所示:

typedef uint32_t LegacyFlags;

struct LegacyFoo {
    uint32_t x;
    uint32_t y;
    LegacyFlags flags;
    // more data
};

struct LegacyBar {
    LegacyFoo foo;
    float a;
    // more data
};

void legacy_input(LegacyBar const* s); // Does something with s
void legacy_output(LegacyBar* s); // Stores data in s
Run Code Online (Sandbox Code Playgroud)

出于各种原因,libModern 不应该向用户公开 libLegacy 的类型,其中包括:

  • libLegacy 是一个不应泄露的实现细节。libModern 的未来版本可能会选择使用另一个库而不是 libLegacy。
  • libLegacy 使用难以使用、容易误用的类型,这些类型不应成为任何面向用户的 API 的一部分。

处理这种情况的教科书方法是 pimpl 习惯用法:libModern 将提供一个包装类型,该类型内部有一个指向遗留数据的指针。然而,这在这里是不可能的,因为 libModern 无法分配动态内存。一般来说,其目标不是增加大量开销。

因此,libModern 定义了自己的类型,这些类型与遗留类型布局兼容,但具有更好的接口。在此示例中,它使用强标志enum而不是普通uint32_t标志:

enum class ModernFlags : …
Run Code Online (Sandbox Code Playgroud)

c++ gcc language-lawyer type-punning c++20

8
推荐指数
1
解决办法
669
查看次数

在 futex 系统调用中使用 std::atomic

在 C++20 中,我们能够在原子变量上休眠,等待它们的值改变。我们通过使用std::atomic::wait方法来做到这一点。

不幸的是,虽然wait已经标准化,wait_forwait_until不是。这意味着我们不能在超时的原子变量上睡觉。

无论如何,使用 Windows上的WaitOnAddress和Linux 上的futex系统调用在幕后实现原子变量睡眠。

解决上述问题(无法在具有超时的原子变量上休眠),我可以在 Windows 上将内存地址传递std::atomic给 toWaitOnAddress并且它将(有点)在没有 UB 的情况下工作,因为该函数void*作为参数获取,并且强制转换std::atomic<type>为有效void*

在 Linux 上,不清楚是否可以std::atomicfutex. futex得到无论是uint32_t*int32_t*(取决于你读这手册),铸造std::atomic<u/int>u/int*为UB。另一方面,手册说

uaddr 参数指向 futex 字。 在所有平台上,futex 都是四字节整数,必须在四字节边界上对齐。在 futex_op 参数中指定要对 futex 执行的操作;val 是一个值,其含义和目的取决于 futex_op。

提示alignas(4) std::atomic<int>应该有效,只要类型具有 4 个字节的大小和 4 的对齐方式,它是哪种整数类型并不重要。

此外,我已经看到很多地方实现了这种结合原子和 futexes 的技巧,包括boostTBB

那么以非 …

c++ linux futex stdatomic c++20

7
推荐指数
1
解决办法
230
查看次数

“reinterpret_cast”真的有什么好处吗?

最近 了解到,通过 ing 其地址将 POD 重新解释为不同的 POD 是未定义行为reinterpret_castreinterpret_cast所以我只是想知道,如果它不能用于其名称所暗示的用途,那么它的潜在用例可能是什么?

c++ casting reinterpret-cast type-punning c++17

3
推荐指数
1
解决办法
2362
查看次数