为什么允许shared_ptr<T[N]>?
Why allow shared_ptr<T[N]>?
这个答案引用了N4082,这表明std::shared_ptr
即将进行的更改将允许T[]
和T[N]
变体:
与
unique_ptr
对数组的部分专门化不同,shared_ptr<T[]>
和shared_ptr<T[N]>
都是有效的,并且都将导致在托管对象数组上调用delete[]
。template<class Y> explicit shared_ptr(Y* p);
要求:
Y
为完整类型。表达式delete[] p
(当T
是数组类型时)或delete p
(当T
不是数组类型时)应该是格式良好的,应该具有良好定义的行为,并且不会抛出异常。当T
为U[N]
时,Y(*)[N]
可转换为T*
;当T
为U[]
时,Y(*)[]
转换为T*
;否则,Y*
必须转换为T*
。
除非我弄错了,Y(*)[N]
只能通过获取数组的地址来形成,显然shared_ptr
不能拥有或删除数组。我也没有看到任何迹象表明N
以任何方式强制管理对象的大小。
允许T[N]
语法背后的动机是什么?它是否产生任何实际的好处,如果有,它是如何使用的?
您可以获得一个指向嵌套对象的指针,该指针与指向包含对象的std::shared_ptr
共享所有权。如果这个嵌套对象恰好是一个数组,并且您想要将其作为数组类型访问,则实际上需要使用T[N]
和合适的T
和N
:
#include <functional>
#include <iostream>
#include <iterator>
#include <memory>
#include <queue>
#include <utility>
#include <vector>
using queue = std::queue<std::function<void()>>;
template <typename T>
struct is_range {
template <typename R> static std::false_type test(R*, ...);
template <typename R> static std::true_type test(R* r, decltype(std::begin(*r))*);
static constexpr bool value = decltype(test(std::declval<T*>(), nullptr))();
};
template <typename T>
std::enable_if_t<!is_range<T>::value> process(T const& value) {
std::cout << "value=" << value << "n";
}
template <typename T>
std::enable_if_t<is_range<T>::value> process(T const &range) {
std::cout << "range=[";
auto it(std::begin(range)), e(std::end(range));
if (it != e) {
std::cout << *it;
while (++it != e) {
std::cout << ", " << *it;
}
}
std::cout << "]n";
}
template <typename P, typename T>
std::function<void()> make_fun(P const& p, T& value) {
return [ptr = std::shared_ptr<T>(p, &value)]{ process(*ptr); };
// here ----^
}
template <typename T, typename... M>
void enqueue(queue& q, std::shared_ptr<T> const& ptr, M... members) {
(void)std::initializer_list<bool>{
(q.push(make_fun(ptr, (*ptr).*members)), true)...
};
}
struct foo {
template <typename... T>
foo(int v, T... a): value(v), array{ a... } {}
int value;
int array[3];
std::vector<int> vector;
};
int main() {
queue q;
auto ptr = std::make_shared<foo>(1, 2, 3, 4);
enqueue(q, ptr, &foo::value, &foo::array, &foo::vector);
while (!q.empty()) {
q.front()();
q.pop();
}
}
在上面的代码中,q
只是一个简单的std::queue<std::function<void()>>
,但我希望你能想象它可能是一个线程池,将处理卸载到另一个线程。实际调度的处理也很琐碎,但是,我希望您能再次想象到它实际上是相当多的工作。
除非我弄错了,
Y(*)[N]
只能通过获取地址来形成一个数组,显然不能被shared_ptr
拥有或删除。
不要忘记shared_ptr
是一个通用的资源管理实用程序,可以用自定义的deallocator来构建:
template<class Y, class D> shared_ptr(Y* p, D d);
这样一个用户提供的deallocator可以执行delete
/delete[]
以外的操作。例如,如果所讨论的数组是一个文件描述符数组,那么"deallocator"可以关闭所有的文件描述符。
在这种情况下,shared_ptr
并不拥有一般意义上的对象,因此可以通过获取其地址来绑定到现有的数组。
- 请解释这句话(cout<<1+int((a<b)^((b-a)&1) )<<endl
- 呼叫运营商<<临时
- 如何防止clang格式在流运算符调用之间添加换行符<<
- <<操作员在下面的行中工作
- EASTL矢量<向量<int>>连续的
- C - 创建矢量&lt; vector&lt; double&gt;&gt;矩阵具有分配而不是inizializ
- 为什么将此对向量&lt; map&lt; int,int&gt;&gt;中的地图进行更新.失败
- C :对矢量进行排序&lt; struct&gt;(结构有2个整数)基于结构的整数之一
- 明确的专业化“ CheckIntmap&lt;&gt;”实例化
- 什么是模板&lt;&gt;inline bla bla
- 编辑C Qlist&lt; object*&gt; gt;QML代码和一些QML警告中的模型
- eigen :: llt&lt;eigen :: matrixxd&gt;具有不完整的类型
- 错误,包括&lt; ctype&gt;在原子上使用C 11
- std::vector<;uint8_t>;当C++11/14启用时,手动复制而不是调用memcpy
- 如何加入向量&lt; int&gt;到C 中的单个INT
- 是std :: set&lt; std :: future&gt;不可能存在
- 是numeric_limits&lt; int&gt; :: is_modulo从逻辑上矛盾
- opencv 2.4.7在iOS错误背景_segm.hpp #include&lt; list&gt;未找到
- 在修改列表后,std :: list&lt; t&gt; :: end()的值是否会更改
- ///<评论></评论>在Visual Studio中