gpt4 book ai didi

c++ - 编译器能否将隐式声明的虚拟析构函数的实现放在一个单独的翻译单元中?

转载 作者:行者123 更新时间:2023-12-04 08:46:51 24 4
gpt4 key购买 nike

以下代码编译并链接到 Visual Studio (2017 年和 2019 年都带有 /permissive- ),但不与 gcc 一起编译或 clang .

foo.h

#include <memory>

struct Base {
virtual ~Base() = default; // (1)
};

struct Foo : public Base {
Foo(); // (2)
struct Bar;
std::unique_ptr<Bar> bar_;
};

foo.cpp

#include "foo.h"

struct Foo::Bar {}; // (3)
Foo::Foo() = default;

main.cpp

#include "foo.h"

int main() {
auto foo = std::make_unique<Foo>();
}


我的理解是,在 main.cpp , Foo::Bar必须是完整类型,因为在 ~Foo() 中尝试删除它,它是隐式声明的,因此在访问它的每个翻译单元中都隐式定义。

然而, Visual Studio不同意,并接受此代码。此外,我发现以下更改使 Visual Studio拒绝代码:
  • 制作 (1)非虚拟
  • 定义 (2)内联 -- 即 Foo() = default;Foo(){};
  • 删除 (3)

  • 在我看来好像 Visual Studio在以下条件下使用它时,不会在任何地方定义隐式析构函数:
  • 隐式析构函数是虚拟的
  • 该类具有在不同翻译单元中定义的构造函数

  • 相反,它似乎只在翻译单元中定义析构函数,该单元还包含第二个条件中构造函数的定义。

    所以现在我想知道:
  • 这是允许的吗?
  • Visual Studio 是否在任何地方指定,或者至少是已知的?做这个?

  • 更新:我已提交错误报告 https://developercommunity.visualstudio.com/content/problem/790224/implictly-declared-virtual-destructor-does-not-app.html .让我们看看专家是如何看待这个问题的。

    最佳答案

    我相信这是 MSVC 中的一个错误。至于std::default_delete::operator() ,标准说[unique.ptr.dltr.dflt/4] :

    Remarks: If T is an incomplete type, the program is ill-formed.



    由于没有“不需要诊断”子句,因此符合 C++ 编译器 需要发出诊断 [intro.compliance/2.2] :

    If a program contains a violation of any diagnosable rule or ..., a conforming implementation shall issue at least one diagnostic message.



    连同 [intro/compliance/1] :

    The set of diagnosable rules consists of all syntactic and semantic rules in this document except for those rules containing an explicit notation that “no diagnostic is required” or which are described as resulting in “undefined behavior”.



    GCC 使用 static_assert诊断类型完整性。 MSVC 似乎不执行这样的检查。如果它默默地传递了一个参数 std::default_delete::operator()delete ,然后,这会导致未定义的行为。这可能与您的观察相符。它可能会工作,但在文档(作为非标准 C++ 扩展)保证之前,我不会使用它。

    关于c++ - 编译器能否将隐式声明的虚拟析构函数的实现放在一个单独的翻译单元中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58506694/

    24 4 0