C++ 使用std::shared_ptr<;无效>;指什么
我在应用程序中使用了一个C++ 使用std::shared_ptr<;无效>;指什么,c++,c++11,stl,shared-ptr,smart-pointers,C++,C++11,Stl,Shared Ptr,Smart Pointers,我在应用程序中使用了一个std::shared_ptr来制作一个智能指针,它可以指向许多不同类型的数据结构,如结构、向量、矩阵。。。基本上什么都可以。我要做的是将一些名称映射到它们的数据结构 我正在使用哈希表执行映射: std::无序地图 我是否可以将find()返回的std::shared_ptr转换回std::shared_ptr?如果是,怎么做 更重要的是,这是一种良好的做法吗?随着应用程序的扩展,这会不会增加太多的复杂性?或者,还有其他完全不同、优雅的方法吗 编辑 可能无法使用'Boos
std::shared_ptr
来制作一个智能指针,它可以指向许多不同类型的数据结构,如结构、向量、矩阵。。。基本上什么都可以。我要做的是将一些名称映射到它们的数据结构
我正在使用哈希表执行映射:
std::无序地图
我是否可以将find()
返回的std::shared_ptr
转换回std::shared_ptr
?如果是,怎么做
更重要的是,这是一种良好的做法吗?随着应用程序的扩展,这会不会增加太多的复杂性?或者,还有其他完全不同、优雅的方法吗
编辑
可能无法使用'Boost.Any',因为它使用RTTI
也不能对所有这些数据结构使用基类,因为其中一些是STL容器,如std::vector
关于下面回答中讨论的shared\u ptr
delete问题,我读到shared\u ptr执行类型擦除,并存储类型信息以知道调用哪个析构函数
但我对此不确定。这不是一个好的做法。如果您没有在
std::shared_ptr
旁边存储额外的类型信息(您可以使用它进行转换),那么您的行为到处都是未定义的。也许这是你的选择
如果您想坚持使用
std::shared\u ptr
,请记住提供一个自定义的删除函数(请参阅)。如果您存储void*
,那么在每个使用点,您都需要知道您输入的确切类型,转换为-void*
,并且只有在您转到/从完全相同的类型返回时才有效(例如,不是派生为从空到基)
考虑到每个使用点都需要知道存储指针的类型,为什么要往返于void呢
每个存储的类型有一个映射。这比每个应用程序有一个映射的开销要小(运行时的内存为O(类型数),编译时类似)
使用C++ >代码>模板< /C> >代码很少重复。 我可以将find()返回的std::shared\u ptr转换回std::shared\u ptr吗?如果可以,如何转换
是的。使用。也就是说,在这种情况下,您需要从void*转换为具体类型的事实很可能是设计不佳的症状 您应该(几乎)永远不需要从void*转换为强类型指针类型(“几乎”意味着我认为您永远不应该这样做,但可能有一些情况我没有考虑过) 更重要的是,这是一种良好的做法吗 不可以。根据经验,只有当您对内存地址的值感兴趣,而对存储的数据根本不感兴趣时,才应该转换为void* 随着应用程序的扩展,这会不会增加太多的复杂性 我能想到的第一个问题是,您的类型不再是在一个地方定义的。这意味着,如果到处都是指针强制转换,当您决定更改类名时,(或者您不再对路径使用std::string,而是使用boost::path对象,等等),则必须遍历所有代码并更新添加的所有强制转换中的所有类型 第二个问题是,随着应用程序的扩展,它会带来这个强制转换问题,并在代码库中传播它,使整个代码库的情况变得更糟因此,可维护性较差。如果在整个代码中存在其他设计折衷,超过一定大小,则应用程序将变得难以维护/禁止维护 这种方法只会使您无法编写松散耦合的代码 或者,还有其他完全不同、优雅的方法吗 检查代码并列出指针上使用的操作。然后,将这些操作作为纯虚拟函数添加到基类中。根据存储值类型实现该基类的具体模板专门化 代码:class pointer\u holder{//获得更好的名称
公众:
虚空传送_指针()=0;//操作示例
虚拟~pointer_holder()=0;
};
模板
类类型\u持有者:公共指针\u持有者{
公众:
//TODO:添加构造函数等
虚空传送_指针(){
//为T实现远程传输\ U指针
}
虚拟~type_holder();
私人:
T值;
};
客户端代码:
std::unordered_map<std::string, std::shared_ptr<pointer_holder>> your_map;
your_map["int"] = new type_holder<int>{10};
your_map["string"] = new type_holder<std::string>{"10"};
your_map["int"]->teleport_pointer(); // means something different for each
// pointer type
std::无序映射您的映射;
你的地图[“int”]=新的类型持有者{10};
你的地图[“字符串”]=新类型的持有者{“10”};
你的映射[“int”]->teleport_pointer();//对每一个元素都有不同的含义
//指针类型
您可以
#include <memory>
#include <iostream>
#include <string>
using namespace std;
class wild_ptr {
shared_ptr<void> v;
public:
template <typename T>
void set(T v) {
this->v = make_shared<T>(v);
}
template <typename T>
T & ref() {
return (*(T*)v.get());
}
};
int main(int argc, char* argv[])
{
shared_ptr<void> a;
a = make_shared<int>(3);
cout << (*(int*)a.get()) << '\n';
cout << *static_pointer_cast<int>(a) << '\n'; // same as above
wild_ptr b;
cout << sizeof(b) << '\n';
b.set(3);
cout << b.ref<int>() << '\n';
b.ref<int>() = 4;
cout << b.ref<int>() << '\n';
b.set("foo");
cout << b.ref<char *>() << '\n';
b.set(string("bar"));
cout << b.ref<string>() << '\n';
return 0;
}
您可能想看看。@JoachimPileborg谢谢您的建议,您能看看我对下面答案的评论吗?为什么RTTI是一个问题?您如何知道
map[“foo”]中存储的类型
?@DavidRodríguez dribeas在应用程序中,我确实知道映射到任何foo
std::shared_ptr
的类型实际上并不调用UB。不是单独调用UB,而是将指针投射到另一个类型(即p
指向基对象,但被投射到派生的)然后取消引用。@谢谢你,请你解释一下UB是如何被引入的。我也觉得我必须考虑Boost。任何一个暗示我的设计都有根本的缺陷。如果我没有错,Booost。任何一个都会引入基于动态的基于行为的行为,这真的是违背C++和它的致盲速度。@实际上现在正在看一些C代码,它使用了<代码> Value*/Cux>指针。但是我真的不想在C++中使用原始指针!使用<代码> STD::SysDypPTR <代码>,这对这里没有帮助。<代码>:STYD:PTR 只有当你有道具时才有意义。
#include <memory>
#include <iostream>
#include <string>
using namespace std;
class wild_ptr {
shared_ptr<void> v;
public:
template <typename T>
void set(T v) {
this->v = make_shared<T>(v);
}
template <typename T>
T & ref() {
return (*(T*)v.get());
}
};
int main(int argc, char* argv[])
{
shared_ptr<void> a;
a = make_shared<int>(3);
cout << (*(int*)a.get()) << '\n';
cout << *static_pointer_cast<int>(a) << '\n'; // same as above
wild_ptr b;
cout << sizeof(b) << '\n';
b.set(3);
cout << b.ref<int>() << '\n';
b.ref<int>() = 4;
cout << b.ref<int>() << '\n';
b.set("foo");
cout << b.ref<char *>() << '\n';
b.set(string("bar"));
cout << b.ref<string>() << '\n';
return 0;
}
3
3
8
3
4
foo
bar