【问题标题】:Can inline member functions differing across compilation units break binary compatibility?编译单元之间不同的内联成员函数会破坏二进制兼容性吗?
【发布时间】:2012-05-20 12:53:01
【问题描述】:

我在一个大项目中有很多代码,它有两种一般类型的代码,一些以很好的 C++ 风格完成,并且已经过 C++ 专家的代码审查,而另一些则没有,也没有。 not 的代码有很多 for 循环和未经检查的数组(堆)访问,包括读取和写入。幸运的是,所有这些对堆的访问都是通过一个类完成的。为了争论,我们称它为CArray

CArray 完全在头文件中定义,因为它是模板化的。大致定义如下(只显示相关部分):

template <typename elementType> class CArray
{
    /// Most of class details I'm leaving out

public:
    inline elementType & operator[](unsigned int i)
    {
#ifdef CARRAY_BOUNDARY_DEBUGGING
        if(i >= m_numElements)
        {
            throw SomeException("CArray::operator[] going out of bounds");
        }
#endif
        return m_pArray[i];
    }

    /// also have corresponding const version of this operator[]

private:
    elementType *m_pArray;
    int m_numElements;
}

(请假设构造函数、析构函数、复制构造函数、赋值运算符和相应的右值引用版本都做对了。基本上假设类的用户正确使用这个类所需的一切。

现在的问题是,如果我有一些定义 CARRAY_BOUNDARY_DEBUGGING 的编译单元(.cpp 文件),然后包含这个类(需要代码改进/审查的那些),但其他没有的(那些坚如磐石):

  1. 如果类经常通过复制、引用和右值引用(仅限 C++11)在 C++03 的编译单元边界上传递,这是否保证可以并且不会引入问题? C++11?

  2. 有没有更好的方法来尝试这样做?

编辑:澄清。我知道非inline 函数必须遵守 C++03 标准第 3.2 节中所述的单一定义规则,但这是内联的。 ODR 是否仍然适用,或者这里还有其他有效的东西?此外,C++03 标准规定“内联函数应在使用它的每个翻译单元中定义。”

【问题讨论】:

    标签: c++ templates inline compilationunit


    【解决方案1】:

    不,不行,是UB。内联定义在整个程序中必须相同。如果你想在某些地方使用额外的逻辑,但不是全部,只需让它成为另一个成员(也写CArray 很傻):

    struct silly_array {
        T& operator[](int x) { /* unchecked */ }
        T& at(int x) { /* check bounds */ return (*this)[x]; }
    };
    

    【讨论】:

    • 仅供参考,这个类比这更复杂,我只是把它归结为要点。
    • 另外,你能指出标准中这是 UB 的位置吗?我认为内联函数不受单一定义规则的约束。还是这是别的什么?
    • @ChrisA.:查看 ISO/IEC 14882:2011 3.2 第 5 段。
    • @ChrisA.:澄清:CatPlusPlus 是完全正确的。允许在多个翻译单元中定义的类、内联函数和其他实体的 odr 声明定义必须相同(即由相同的标记序列组成,每个名称都指代“相同”的事物)。
    • @ChrisA:或多或少。请注意,“令牌”(2.6)表示预处理之后。在预处理之前,它们是“预处理令牌”(2.4)。所以在没有定义CARRAY_BOUNDARY_DEBUGGING的翻译单元中,定义你的函数的标记序列是{}。在带有CARRAY_BOUNDARY_DEBUGGING 的TU 中,情况有所不同,以{if( 开头。所以违反了 ODR。
    【解决方案2】:

    您忘记阅读您引用的句子的其余部分。 7.1.2(4) “内联函数应在使用它的每个翻译单元中定义并且在每种情况下都应具有完全相同的定义 (3.2)。”

    【讨论】:

      猜你喜欢
      • 2018-12-27
      • 1970-01-01
      • 2015-07-06
      • 1970-01-01
      • 1970-01-01
      • 2012-09-24
      • 2014-07-15
      • 2013-03-08
      • 1970-01-01
      相关资源
      最近更新 更多