C++ 共享_数组的元素作为共享_ptr?
如果我有一个C++ 共享_数组的元素作为共享_ptr?,c++,boost,c++11,shared-ptr,C++,Boost,C++11,Shared Ptr,如果我有一个boost::shared_数组(或boost::shared_ptr),有没有办法获得与数组共享的boost::shared_ptr 例如,我可能想写: shared_array<int> array(new int[10]); shared_ptr<int> element = &array[2]; 不幸的是,我找不到这样的东西。shared_ptr上有一个别名构造函数,它将与另一个shared_ptr别名,但它不允许与shared_数组别名;所
boost::shared_数组
(或boost::shared_ptr
),有没有办法获得与数组共享的boost::shared_ptr
例如,我可能想写:
shared_array<int> array(new int[10]);
shared_ptr<int> element = &array[2];
不幸的是,我找不到这样的东西。shared_ptr
上有一个别名构造函数,它将与另一个shared_ptr
别名,但它不允许与shared_数组
别名;所以我也不能写这个(它不会编译):
接下来我将尝试升级到Boost 1.53.0(我们目前只有1.50.0),使用shared_ptr
而不是shared_array
,并且始终使用Boost
而不是std
(即使对于非数组)。我希望这会奏效,但我还没有机会尝试:
shared_ptr<int[]> array(new int[10]);
shared_ptr<int> element(array, &array[2]);
shared_ptr数组(新int[10]);
共享_ptr元素(数组和数组[2]);
当然,我仍然更喜欢实例方法语法,但我想我不太可能使用它(除了修改Boost):
shared_ptr element=array.shared_ptr_to(2);
还有人有什么想法吗?你在做奇怪的事情。 为什么您需要
共享\u ptr
到元素?是否要将数组的元素传递到其他位置并阻止移除数组
如果是,则比
std::vector
更适合这样做。该解决方案是安全的、标准的,并且在对象删除方面具有很好的粒度boost::shared_ptr
似乎不支持本机的这一功能。也许你可以用一个自定义的删除器来解决这个问题。但是std::shared_ptr
提供了一个特殊的构造函数来支持您想要的:
struct foo
{
int a;
double b;
};
int main()
{
auto sp1 = std::make_shared<foo>();
std::shared_ptr<int> sp2 (sp1,&sp1->a);
}
structfoo
{
INTA;
双b;
};
int main()
{
自动sp1=std::使_共享();
std::shared_ptr sp2(sp1,&sp1->a);
}
这里,
sp1
和sp2
共享foo
对象的所有权,但sp2
指向它的一个成员。如果sp1
被销毁,则foo
对象仍将处于活动状态,sp2
仍将有效。以下是我最后所做的
我自己实现了共享_数组
。它有效地扩展了shared\u ptr
,除了它实际上扩展了我自己的vector
包装器,这样用户就无法取出向量。这意味着我可以保证它不会被调整大小。然后我实现了我所需要的实例方法,包括weak\u ptr\u to(size\u t)
当然还有operator[]
我的实现使用std::make_shared
生成向量。因此,向量独立于控制块分配其内部阵列存储,但向量本身成为控制块的一个成员。因此,这相当于忘记对普通类型使用std::make_shared
——但是因为这些是数组,它们可能是大而少的,所以就不那么重要了
我还可以创建一个基于shared\u ptr
的实现,但是使用default\u delete
或任何需要的东西,但是它必须与控制块分开分配数组(因此与矢量相比没有太多节省)。我不认为有一种可移植的方法可以在控制块中嵌入动态大小的数组
或者我的实现可以基于boost::shared_array
,并在获取元素指针时使用自定义删除器(如问题中的示例所示)。在大多数情况下,这可能更糟糕,因为不是一次性命中分配数组,而是每次获取别名指针时都会命中一次(对于寿命很短的指针,这种情况可能会经常发生)
我认为让它变得更优化的唯一合理方法是使用最新的boost(如果它有效的话;在我改变主意之前,我没有尝试过它,主要是因为我对自己的实例成员的渴望)。当然,这意味着在任何地方都要使用boost
one,即使对于单个对象也是如此
但是,我使用的主要优点是Visual Studio的调试器(听说)擅长显示std::shared_ptrs和std::vectors的内容,并且(我们期望)不太擅长分析boost内容或自定义内容
因此,我认为我所做的基本上是最佳的 你的想法是应该这样做的。它没有什么特别低效的地方(如果有疑问,请使用探查器运行一个实验)。@n.m.我认为它会为新的
共享\u ptr
创建一个新的控制块(在堆上)。虽然没有那么糟糕,但如果它可以共享同一个控制块,那就更好了。:)您是否需要一个共享_数组
?如果您有一个共享的\u ptr
(带有适当的deleter),您可以使用别名构造函数。我已经考虑过了。唯一缺少的就是操作符[]
。我将发布一个答案,说明我最后做了什么。是的,我希望整个数组都能保留,只要我有一个指向任何元素的指针。这种情况会发生在API为了安全而采用共享的\u ptr时,但有时我们会同时分配许多类似的对象,并希望将堆开销降到最低。同时,应用程序的其余部分并不特别需要知道对象来自数组虽然,我认为弱ptr可能更适合这些情况,但当然,上述所有问题仍然适用,但在某些地方,稍微调整一下说弱ptr而不是共享ptr。@entheh那么数组的生存期呢,它什么时候发布呢?任何拥有数组共享ptr的对象都将负责该问题。但例如,有时我可能会将弱ptr带到元素,并将它们提供给Lua,并且总会有人意外地在Lua中保留对象太长时间。我们希望在这种情况下有明确的行为,仅此而已。)我不确定
template<typename T>
boost::shared_ptr<T> GetElementPtr(const boost::shared_array<T> &array, size_t index) {
//This deleter works by holding on to the underlying array until the deleter itself is deleted.
struct {
boost::shared_array<T> array;
void operator()(T *) {} //No action required here.
} deleter = { array };
return shared_ptr<T>(&array[index], deleter);
}
shared_ptr<int[]> array(new int[10]);
shared_ptr<int> element(array, &array[2]);
shared_ptr<int> element = array.shared_ptr_to(2);
struct foo
{
int a;
double b;
};
int main()
{
auto sp1 = std::make_shared<foo>();
std::shared_ptr<int> sp2 (sp1,&sp1->a);
}