gpt4 book ai didi

c++ - 引用类型删除的 void*

转载 作者:行者123 更新时间:2023-11-30 03:14:32 29 4
gpt4 key购买 nike

我正在实现一个允许处理旧数据类型保存的迭代器适配器 void* ,我想得到一个 forward_iterator通过为用户提供保存在该结构中的真实指针的 View ,允许交换该旧数据类型的值。示例:

auto it = iterator_adaptor<T*>(pos);

哪里pos->objectvoid*最初的类型是 T* .问题是关于引用类型:

// within iterator_adaptor
typedef T*& reference;

// I want to promise that to the user.
typedef std::forward_iterator_tag iterator_category;

reference operator*() const { return static_cast<reference>(_pos->object); }

这会产生编译器错误,因为我无法将引用包装在不同类型的对象上。如果类型相关,我可以在引用之间或指针之间进行转换,但我怎么能转换 void*左值为 T*&以一种非未定义的行为方式,知道 _pos->object指向 T 类型的对象?

我能想到的唯一可能被编译器吞掉的是:

return *reinterpret_cast<T**>(&_pos->object);

或者这个方向的东西,但是标准必须以 100% 的概率将其定义为未定义的行为。

注意:我想返回一个 T*& , 不是 T& , 因为每个 T 的一些语义由它的地址定义(具体来说,有哈希表将 T::id() 映射到它的地址,因为每个 T::id() 对于每个 T* 都是唯一的)。如果我返回 T&然后用户交换它们,地址和id不再匹配,举一些可能破坏应用程序的例子。我宁愿允许用户交换每个 T* 的位置在结构中(因为用户毕竟保存了指针;每个 T 都是在插入结构之前动态创建的),例如个性化其排序,或使用任何 std需要前向和输入迭代器的算法。

实际上,“交换”位置的事情并不是那么重要,而是使用 <algorithm>需要前向迭代器的算法库是我想提供的一个功能。

最佳答案

好吧,让我直截了本地说(一个 mcve 会有很大帮助):

你有这种情况:

X x1{}, x2;
X* p = &x1;

void* vp = reinterpret_cast<void*>(p);

// p is lost

// here you want to recover p such that:
X*& q = /* something magic from vp */;
q = &x2; // this will modify p

如果是这种情况,那根本不可能,因为您丢失了对象 p永远。您保存在 vp什么p pointed,也就是你保存了它的值,也就是你保存了 x1 的地址(以类型删除的方式)并且是可恢复的,指针是可恢复的(如果你知道原始类型),但是 p丢失了,它从未被保存。


如果要恢复p那么你需要保存它的地址:

X x1{11}, x2{27};
X* p = &x1;

void* vpp = reinterpret_cast<void*>(&p);

// p must not end lifetime !! very important

X*& q = *reinterpret_cast<X**>(vpp);
q = &x2; // will indeed modify p (p must still be alive)

否则你可以这样做,这是完全有效的:

T& a = *reinterpret_cast<T*>(pos->object);
T* p = reinterpret_cast<T*>(pos->object);

最后是一些标准甜点(重点是我的):

§8.5.1.10 Reinterpret cast [expr.reinterpret.cast]

  1. An object pointer can be explicitly converted to an object pointer of a different type. 73 When a prvalue v of object pointer type is converted to the object pointer type “pointer to cv T”, the result is static_cast<cv T*>(static_cast<cv void*>(v)). [ Note: Converting a prvalue of type “pointer to T1” to the type “pointer to T2” (where T1 and T2 are object types and where the alignment requirements of T2 are no stricter than those of T1) and back to its original type yields the original pointer value. — end note ]

在最简单的例子中:

X* p = /* ... */;

void* v = reinterpret_cast<void*>(p);

X* q = reinterpret_cast<X*>(v);

// q is guaranteed to have the original value of p,
// i.e. p == q is true

关于c++ - 引用类型删除的 void*,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57734212/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com