C++23中unique_ptr的nullptr初始化规则是否变更?编译器行为差异求证
C++23下std::unique_ptr与不完全类型的编译分歧问题
以下代码在VS2022的MSVC编译器C20模式下可正常编译,但切换到C23模式(/std:c++latest)时编译失败:
#include <memory> struct A; struct B { B(); ~B(); std::unique_ptr<A> ptr{nullptr}; }; int main(){ B b; }
当前版本的GCC和Clang在C++23模式下均可正常编译该代码。
MSVC在C++23模式下的报错信息如下:
C:/data/msvc/14.38.33133/include\memory(3169): error C2027: use of undefined type 'A' <source>(3): note: see declaration of 'A' C:/data/msvc/14.38.33133/include\memory(3169): note: the template instantiation context (the oldest one first) is <source>(9): note: see reference to class template instantiation 'std::unique_ptr<A,std::default_delete<A>>' being compiled C:/data/msvc/14.38.33133/include\memory(3205): note: see reference to class template instantiation 'std::default_delete<A>' being compiled C:/data/msvc/14.38.33133/include\memory(3168): note: while compiling class template member function 'void std::default_delete<A>::operator ()(_Ty *) noexcept const' with [ _Ty=A ] C:/data/msvc/14.38.33133/include\memory(3280): note: see the first reference to 'std::default_delete<A>::operator ()' in 'std::unique_ptr<A,std::default_delete<A>>::~unique_ptr' C:/data/msvc/14.38.33133/include\memory(3169): error C2338: static_assert failed: 'can't delete an incomplete type' C:/data/msvc/14.38.33133/include\memory(3170): warning C4150: deletion of pointer to incomplete type 'A'; no destructor called <source>(3): note: see declaration of 'A'
微软技术支持表示,该新行为源于C++23中std::unique_ptr被赋予了constexpr特性,他们只是遵循标准要求。
核心疑问
- 微软的上述说法是否正确?
- GCC和Clang在C++23模式下接受该代码是否属于编译错误?
补充说明
- 代码中调用
std::unique_ptr<A>的构造函数时,因用nullptr初始化,不会涉及不完全类型A的构造,这部分在MSVC的C++23模式下无问题。 std::unique_ptr<A>的析构函数并未在此编译单元中被调用,而是在B的析构函数中执行,而B的析构函数定义在另一个源文件中,其中A是完整类型。该逻辑在GCC、Clang及MSVC的C20模式下均能正常工作,但MSVC在C23模式下却因A是不完全类型,提前触发了std::unique_ptr<A>析构函数的实例化。- 开发者认为当前编译单元不应触发析构函数的实例化,但微软支持称这是C++23的合理行为,根源在于
std::unique_ptr的constexpr特性。
内容的提问来源于stack exchange,提问作者Benjamin Buch
相关产品推荐
相关产品推荐

