我看到这篇文章vector of structs inline initialization. braced-init-list中描述了一些奇怪的行为

我希望消除这种不确定行为的一种可能来源。我有以下两个类AB,它们都向前声明struct Foo,但cpp文件定义了如下的实际结构。

// This is A.h
namespace app {
    struct Foo;
    class A {
    private:
        std::vector<Foo> fooList;
    };
}

// This is A.cpp
struct app::Foo {
    std::string first;
    std::string second;
    unsigned flag;
};


// This is B.h
namespace app {
    struct Foo;
    class B {
    private:
        std::vector<Foo> fooList;
    };
}

// This is B.cpp
struct app::Foo {
    std::string first;
    std::string second;
    bool flag;
    float value;
};

注意,struct Foo在cpp文件A.cppB.cpp中具有不同的成员。类AB从不公开成员fooList。由于前向声明完全相同,因此是否有可能,在结构A.h的文件B.hFoo中,生成的代码可以使用另一个。这可以解释我在链接问题中看到的问题。

换句话说,在对在Foo中调用的struct B.cpp使用braced-init-list的同时,是否保证将使用在Foo中定义的B.cpp,或者是否有可能也可以使用在Foo中定义的A.cpp

即使在撰写本文时,我也立即意识到这种实现是一种不好的做法,因为Foo本身在AB类的内部,并且实际上应该在该类本身的私有(private)部分中声明。

最佳答案

这违反了ODR(一个定义规则)。

该程序格式不正确,无需诊断。

如果这样做,C++标准绝对允许任何行为。它可以“工作”,可以选择一个并丢弃另一个,可以工作直到重新链接,然后可以格式化硬盘。

我是在一个真实的现场项目中完成的;我们有一个矩阵 header ,可以在其中包含 token (如果它支持float或double),那么可以在其中定义 token 。

在我们从未在同一个DLL中使用两个版本的情况下,这种方法“有效”。然后我们使用了两个版本。

编译器将基于一组巧合为结构选择一个大小或其他大小,并根据一组稍有不同的巧合选择一个构造函数或其他构造函数。我们有大量的内存损坏问题。但仅在某些版本上才有。

我们通过将代码包装在名称包括标量类型的 namespace 中来快速“修复”它,然后using将它们带入外部 namespace 。

10-08 08:20
查看更多