英文:
Restricting the address space of a pointer
问题
理论问题:智能指针的机制一直让我思考不已,尤其是(在这个讨论串的启发下)它们如何进行优化(或者至少,我们如何在性能和可寻址空间之间权衡)。
据我理解,最简单的智能指针包含两个值:一个地址和一个静态引用计数(也是一个地址)。
template<typename T> class ptr {
private:
T* ptr;
int* ref;
// ... 等等。
};
问题: 有没有办法将这两个指针都适应到一个64位地址空间中,并且这样做会对性能和可寻址内存空间有什么影响?
我的想法: 这样,智能指针就可以在64位机器上放入一个寄存器中,这样它就具有与原始指针类似的特性(我想象中)。由于我们有两个指针,我猜想我们的内存空间将限制为2^32吗?我不确定这会带来什么影响,或者在64位空间内是否可行(这样管理会不会成为噩梦?)。
英文:
I have a theoretical question. I've recently found myself thinking about the mechanics of smart pointers, and (largely inspired by this thread) how they can be optimized (or, at least, how we can trade-off performance with addressable space).
To my understanding, the simplest possible smart pointer refers to two values: an address, and a static reference count (also an address).
template<typename T> class ptr {
private:
T* ptr;
int* ref;
// ... etc.
};
Question: Is there a way to fit both pointers within one 64 bit address space, and what would the implications be for both performance and addressable memory space?
My thoughts: The smart pointer then fits in a single register on a 64 bit machine, which (I imagine) would make it have similar qualities to a raw pointer. As we have two pointers, I suppose that our memory space would be limited to 2^32? I'm not sure what the implications of that would be, or if it is possible within a 64 bit space (would managing this be a nightmare?).
答案1
得分: 1
如果您只进行像make_shared
这样的分配,其中对象在控制块旁边分配,您可以完全摆脱T* ptr
(有效地将地址限制为直接在控制块之后):
struct alignas(std::alignmax_t) control_block {
atomic_long shared_count;
atomic_long weak_count;
};
template<typename T> class ptr {
private:
T* get_ptr() const { return reinterpret_cast<T*>(ref+1); }
control_block* ref;
};
这本质上相当于使用boost::intrusive_ptr
,它也具有单个指针的开销。
您还可以将T*
指针存储在控制块中。
如果您使用这两种方法之一,那么只支持将转换为第一个基类,因为指针与控制块紧密相关。
英文:
If you only do allocations like make_shared
, where the object is allocated next to the control block, you can get rid of T* ptr
entirely (effectively restricting the address to be directly after the control block):
struct alignas(std::alignmax_t) control_block {
atomic_long shared_count;
atomic_long weak_count;
};
template<typename T> class ptr {
private:
T* get_ptr() const { return reinterpret_cast<T*>(ref+1); }
control_block* ref;
};
This is essentially equivalent to using a boost::intrusive_ptr
, which also has the overhead of a single pointer.
You could also store the T*
pointer in the control block.
If you use either of these approaches, only casting to the first base class would be supported, since the pointer is inherently tied to the control block.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论