标题

时间:2018-06-04 11:15:15

标签: c++ pointers constexpr

我在头文件中有以下代码,它包含在2个不同的cpp文件中:

constexpr int array[] = { 11, 12, 13, 14, 15 };
inline const int* find(int id)
{
    auto it = std::find(std::begin(array), std::end(array), id);
    return it != std::end(array) ? &*it : nullptr;
}

然后我在每个cpp文件中调用find(13)。将find()返回的两个指针指向内存中的同一地址吗?

我问的原因是因为我的项目中有类似的代码,有时它有效,有时它不会。我假设两个指针都指向同一个位置,但我并不真正有这个假设的基础:)

2 个答案:

答案 0 :(得分:7)

在C ++ 11和C ++ 14中:

在您的示例array中有内部链接(请参阅[basic.link]/3.2),这意味着它将在不同的翻译单元中具有不同的地址。

因此,在不同的翻译单元中包含和调用find是违反ODR的(因为它的定义不同)。

一个简单的解决方案是声明它extern

在C ++ 17中:

[basic.link]/3.2已更改,constexpr可以是inline,在这种情况下将会no effect on the linkage

这意味着,如果您声明array inline,它将具有外部链接,并且在翻译单元之间具有相同的地址。当然,与任何inline一样,它必须在所有翻译单元中具有相同的定义。

答案 1 :(得分:3)

我不能声称自己是这方面的专家,但根据this blog post,你所拥有的代码应该在C ++ 17中做你想要的 ,因为constexpr然后隐含inline,该页面显示(我相信):

  

声明内联的变量与内联声明的函数具有相同的语义:它可以在多个转换单元中相同地定义,必须在使用它的每个转换单元中定义,并且程序的行为如下如果只有一个变量。

所以,有两件事要做:

  • 确保您正在编译为C ++ 17
  • array声明为constexpr inline以强制旧编译器出现编译错误(并确保您实际获得所需的语义 - 请参阅下面的注释)

我相信会这样做。