这是我的问题:有时我在函数中定义了一个std :: string。由于异步操作,我需要扩展字符串的范围。当然,我可以将它复制到这样的共享指针:
{
std::string hi{"hi"};
auto shared_hi = std::make_shared<std::string>(hi);
//insert shared_hi in async queue
}
这个问题是有时我的字符串非常非常大,有时它们是向量,有时它们是std :: arrays。所以我不仅要避免副本,而且我还希望有一个可以“偷”&#34;容器中的数据无需复制。我在下面发布了一个聪明的解决方案,但我想知道是否有更好的解决方案。如果没有,我想知道我在下面做的事情是否定义了行为:
template<class T>
class WrappedDeleter {
public:
WrappedDeleter(T &&other): o_(std::move(other)) {
}
private:
T o_;
};
//This function creates a deleter where the scope
template<class P, class T>
std::function<void(P *)> make_delete(T &&encapsulate) {
WrappedDeleter<T> *d = new WrappedDeleter<T>(std::move(encapsulate));
return [d](P * ptr) {
std::cout << "deleting now\n";
delete d;
};
}
template<class P, class C>
std::shared_ptr<P> steal_data(C &&data) {
P *ptr = data.data();
//can't use make_shared - custom deleter
return std::shared_ptr<P>(ptr, make_delete<P, C>(std::move(data)));
}
像这样使用:
int main() {
{
std::shared_ptr<int> p_a;
std::shared_ptr<int> p_b;
std::shared_ptr<const char> p_c;
{
std::array<int,3> a= {{1,2,3}};
std::vector<int> b= {1,2,3};
std::string c= {"hello world"};
p_a = steal_data<int,std::array<int,3> >(std::move(a));
p_b = steal_data<int, std::vector<int> >(std::move(b));
p_c = steal_data<const char, std::string>(std::move(c));
std::cout << "inside" << *p_a << " " << *p_b << " " << p_c.get() << std::endl;
}
std::cout << "outside" << *p_a << " " << *p_b << " " << p_c.get() << std::endl;
std::cout << "end of scope\n";
}
return 0;
}
答案 0 :(得分:2)
正如Praetorian所说,将数据移入shared_ptr
的唯一合理方法是使用make_shared<T>(move(obj))
。如果您希望shared_ptr
指向基础连续数据块而不是容器本身,则可以使用别名构造函数template<class Y> shared_ptr(const shared_ptr<Y>& r, T *ptr);
:
std::vector<int> v{1, 2, 3};
auto cptr = std::make_shared<std::vector<int>>(std::move(v));
std::shared_ptr<int> ptr{cptr, cptr->data()};
作为一项功能:
template<typename Container>
std::shared_ptr<Container::value_type> steal_data(Container &&cont) {
auto cptr = std::make_shared<Container>(std::move(cont));
return {cptr, cptr->data()};
}