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