[{"data":1,"prerenderedAt":115},["ShallowReactive",2],{"\u002F2020-03-31-note-tweakobjectptr-compile":3},{"id":4,"title":5,"body":6,"date":91,"description":12,"extension":92,"meta":93,"navigation":96,"path":108,"seo":109,"stem":110,"tags":111,"__hash__":114},"blogs\u002F_legacy\u002F2020\u002F2020-03-31-note-tweakobjectptr-compile.md","记录TWeakObjectPtr的一个比较坑的编译报错",{"type":7,"value":8,"toc":85},"minimark",[9,13,16,19,22,25,29,32,43,46,49,52,55,61,64,70,73,79,82],[10,11,12],"p",{},"最近在使用TWeakObjectPtr时遇到了一个比较奇怪的编译报错，记得之前解决过，后面又忘记了，所以这次记录下来。",[10,14,15],{},"为了防止UObject的生命周期混乱问题，官方的建议是加上UProperty。但是有的时候考虑到引用关系的维护，我们不希望使用UProperty来维护指针。",[10,17,18],{},"而且，如果一个指针并不会给蓝图使用却加上了UProperty的话，会无端的感觉很“重”。",[10,20,21],{},"如果不希望控制指针的生命周期，而又希望维护引用的话，可以使用TWeakObjectPtr。如果希望自己保护生命周期的话，可以使用TSharedPtr。TSharedPtr记得如果使用不当的话会有二次释放的问题，不过现在记不清楚触发方式了。",[10,23,24],{},"这边还是回答奇怪的编译错误上吧。",[26,27,28],"h2",{"id":28},"编译错误",[10,30,31],{},"在对裸指针进行保护时，使用TWeakObjectPtr后出现了这样的报错：",[33,34,39],"pre",{"className":35,"code":37,"language":38},[36],"language-text","2>xxx\\engine\\source\\runtime\\core\\public\\UObject\u002FWeakObjectPtrTemplates.h(55): error C2338: TWeakObjectPtr can only be constructed with UObject types\n2>xxx\\engine\\source\\runtime\\core\\public\\UObject\u002FWeakObjectPtrTemplates.h(50): note: while compiling class template member function 'TWeakObjectPtr\u003CAAwesomeActor,FWeakObjectPtr>::TWeakObjectPtr(const T *)'\n2>        with\n2>        [\n2>            T=AAwesomeActor\n2>        ]\n2>Project\\(62): note: see reference to function template instantiation 'TWeakObjectPtr\u003CAAwesomeActor,FWeakObjectPtr>::TWeakObjectPtr(const T *)' being compiled\n2>        with\n2>        [\n2>            T=AAwesomeActor\n2>        ]\n2>Project\\(62): note: see reference to class template instantiation 'TWeakObjectPtr\u003CAAwesomeActor,FWeakObjectPtr>' being compiled\n","text",[40,41,37],"code",{"__ignoreMap":42},"",[10,44,45],{},"编译器似乎不认识我们的AAwesomeActor，使用各种forward declaration反而让问题越来越复杂。",[10,47,48],{},"但是我们又不想破坏include隔离，还是少许有些尴尬。",[26,50,51],{"id":51},"原因",[10,53,54],{},"其实这个错误是因为一个“坏”习惯造成的，通常为了避免忘记写初始化的情况，我们会给指针赋个初始值，改造之后就变成了这样：",[33,56,59],{"className":57,"code":58,"language":38},[36],"TWeakObjectPtr\u003CAAwesomeActor> MyAwesomeActor = nullptr;\n",[40,60,58],{"__ignoreMap":42},[10,62,63],{},"这样的话就导致模板编译的时候进入了“错误”的分支，在WeakObjectPtrTemplates.h中报错的行上面其实可以看到解释：",[33,65,68],{"className":66,"code":67,"language":38},[36],"\u002F\u002F This static assert is in here rather than in the body of the class because we want\n\u002F\u002F to be able to define TWeakObjectPtr\u003CUUndefinedClass>.\nstatic_assert(TPointerIsConvertibleFromTo\u003CT, const volatile UObject>::Value, \"TWeakObjectPtr can only be constructed with UObject types\");\n",[40,69,67],{"__ignoreMap":42},[10,71,72],{},"结论上来说，只要不加初始化就可以了，让模板编译走默认的构造函数就不会进到这里。",[33,74,77],{"className":75,"code":76,"language":38},[36],"TWeakObjectPtr\u003CAAwesomeActor> MyAwesomeActor;\n",[40,78,76],{"__ignoreMap":42},[10,80,81],{},"也就是说，这里初始化就会造成画蛇添足的效果。",[10,83,84],{},"有时候比较着急的时候一下子想不起来就真的比较郁闷。",{"title":42,"searchDepth":86,"depth":87,"links":88},2,3,[89,90],{"id":28,"depth":86,"text":28},{"id":51,"depth":86,"text":51},"2020-03-31","md",{"layout":94,"status":95,"published":96,"author":97,"author_login":99,"author_email":100,"wordpress_id":101,"wordpress_url":102,"date_gmt":103,"excerpt":104},"post","publish",true,{"display_name":98,"login":99,"email":100,"url":42},"风铃","flinkor","flinkor@foxmail.com",2781,"\u002F?p=2781","2020-03-31 14:17:22 +0000",{"type":7,"value":105},[106],[10,107,12],{},"\u002F2020-03-31-note-tweakobjectptr-compile",{"title":5,"description":12},"_legacy\u002F2020\u002F2020-03-31-note-tweakobjectptr-compile",[112,113],"UE4","Smart Pointer","66eOSSicIZqmQ-fcthAADAoN-Z7TkL2xVYC867SVlGg",1788763179043]