为什么允许shared_ptr< T [N]> ;? [英] Why allow shared_ptr<T[N]>?
问题描述
此答案引用了 N4082 ,表明即将对 std :: shared_ptr
进行的更改将同时允许 T []
和 T [N]
变体:
This answer cites N4082, which shows that the upcoming changes to std::shared_ptr
will allow both T[]
and T[N]
variants:
不同于
unique_ptr
数组的部分专业化,两者shared_ptr< T []>
和shared_ptr< T [N]>
是有效的,并且两者都会导致delete []
被删除
Unlike the
unique_ptr
partial specialization for arrays, bothshared_ptr<T[]>
andshared_ptr<T[N]>
will be valid and both will result indelete[]
being called on the managed array of objects.
template<class Y> explicit shared_ptr(Y* p);
要求: Y
应为完整类型。当 T
是数组类型或 delete p <时,表达式
delete [] p
/ code>,当 T
不是数组类型时,其格式应正确,行为应明确定义且不得引发异常。当 T
为 U [N]
时, Y(*)[N]
应可转换为 T *
;当 T
是 U []
时, Y(*)[]
应可转换为 T *
;否则, Y *
应可转换为 T *
。
Requires: Y
shall be a complete type. The expression delete[] p
, when T
is an array type, or delete p
, when T
is not an array type, shall be well-formed, shall have well defined behavior, and shall not throw exceptions. When T
is U[N]
, Y(*)[N]
shall be convertible to T*
; when T
is U[]
, Y(*)[]
shall be convertible to T*
; otherwise, Y*
shall be convertible to T*
.
除非我弄错了,否则 Y(*)[N]
只能由接受数组的地址,该地址显然不能由 shared_ptr
拥有或删除。我也没有看到任何迹象表明以任何方式使用 N
强制管理对象的大小。
Unless I'm mistaken, a Y(*)[N]
could only be formed by taking the address of an array, which clearly can't be owned or deleted by a shared_ptr
. I also don't see any indication that N
is used in any way to enforce the size of the managed object.
允许 T [N]
语法的动机是什么?它会产生任何实际的好处吗?如果是的话,如何使用它呢?
What is the motivation behind allowing the T[N]
syntax? Does it yield any actual benefit, and if so, how is it used?
推荐答案
您可以获得指向嵌套对象的指针与 std :: shared_ptr
共享包含对象的所有权。如果此嵌套对象恰好是一个数组,并且您想以数组类型访问它,则实际上需要使用 T [N]
和合适的 T
和 N
:
You can get a pointer to a nested object sharing ownership with a std::shared_ptr
to the containing object. If this nested object happens to be an array and you want to access it as an array type, you actually need to use T[N]
with suitable T
and 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()>>
,但我希望您可以想象它可以是线程池,将处理卸载到另一个线程。实际计划的处理也是微不足道的,但是我希望您可以想象,这实际上是大量工作。
In the above code q
is just a simple std::queue<std::function<void()>>
but I hope you can imagine that it could be a thread-pool off-loading the processing to another thread. The actually scheduled processing is also trivial but, again, I hope you can imagine that it is actually some substantial amount of work.
这篇关于为什么允许shared_ptr< T [N]> ;?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!