【问题标题】:Declaration or Definition声明或定义
【发布时间】:2011-06-11 22:00:56
【问题描述】:

下面和这句话下面的代码行是否被视为声明或定义?

extern const int &ri;

【问题讨论】:

    标签: c++


    【解决方案1】:

    这是一个声明——“外部”意味着它存在于其他地方。

    【讨论】:

    • extern 的存在并不一定意味着这不是一个定义。例如,extern const int &ri = 42;一个定义。说“extern 意味着它生活在其他地方”是不正确的。 extern 表示名称具有外部链接。它没有说明名称背后的实体居住在哪里。它可以存在于此处或其他地方,具体取决于声明的其他细节(例如,初始化器的存在)。
    • @AndreyT 他说 the “extern”。我认为他指的是该令牌的这种特定用途。在这种情况下,extern 是该声明不是定义所必需的。 +1 表示正确的(如果是微妙的)答案。
    • @Johannes Schaub - litb:好吧,好吧。也许我错过了那个细微差别。将我的评论解释为额外的旁注。另外,我没有投反对票。 (尽管曾经可能会争辩说不是extern存在,而是初始化器的不存在 使它成为非定义声明。)跨度>
    【解决方案2】:

    C++03,§3.1,¶2:

    声明是一个定义,除非...它包含外部说明符或链接说明,既不是初始化程序也不是函数体...

    所以,extern const int &ri;,它包含 extern 说明符而不是初始化器是声明而不是定义。

    【讨论】:

      【解决方案3】:

      首先,声明定义不是相互排斥的概念。每个定义同时是一个声明(很少有例外)。这意味着提出问题的正确方法是:“这是定义声明还是非定义声明?”。

      请注意,我并不是说现在的问题毫无意义。这个问题很好,因为每个人都明白它的真正含义。我只是想把这作为一个介绍性说明。

      其次,这里有一个非定义声明,这意味着该声明不是定义(带有 extern 说明符但没有初始化器的引用或对象声明不是定义)。

      万一

      extern const int &ri = 5;
      

      我们也有一个声明,但这将是一个定义声明(即一个恰好是定义的声明)。

      【讨论】:

      • 如果有两个翻译单元包含extern const int &ri = 5;会怎样?
      • @David Heffernan:在 C++ 中,这将违反 ODR - 具有外部链接的同一实体的多个定义。在 C 中,这也是同类错误。然而,在 C 中允许多个相同的定义一直是一个流行的扩展(甚至在 C 标准中提到)。看到一些 C++ 编译器也实现了该扩展,我不会感到惊讶,尽管 C++ 编译器在这方面通常更严格。
      • @AndreyT:很抱歉在这里发表此评论,但您似乎没有从聊天中收到通知:您不必删除您的答案here,我编辑了问题并原来的没有提到是打开一个新的命名空间还是扩展一个现有的命名空间。
      • @Xeo:我认为原始问题中的注释“在 foo 中打开嵌套命名空间栏并扩展它”意味着扩展现有命名空间。
      • @AndreyT:我发表了评论,最初的问题没有暗示什么意思。
      【解决方案4】:
      extern const int &ri;
      

      它只是一个没有定义的声明,这表明该变量在其他地方定义

      这样的代码通常.h文件中找到,它的定义在.cpp文件中找到。如果您将头文件包含在多个文件中,则此方法用于避免多次重定义错误。像这样的:

      //lib.h
      extern Type object; //declaration Only;
      
      //lib.cpp
      #include "lib.h"
      Type object = /*some initialization - optional*/; //definition
      
      //A.cpp
      #include "lib.h"
      Type oA = object;
      
      //B.cpp
      #include "lib.h"
      Type oB = object;
      

      const在命名空间级别的使用使得被声明或定义的变量具有内部链接,它变得像一个不可变 static变量,它只存在于它自己的翻译单元中.

      extern const使变量具有外联性,同时变量是常数。

      namespace N
      {
          const int i = 10;         //i has internal linkage
          extern const int j = 10;  //j has external linkage
      }
      

      在这种情况下,extern 用于使变量具有外部链接!

      §3.5/3 [basic.link]:

      具有命名空间范围的名称 (3.3.5) 如果是名称,则具有内部链接
      — 对象、引用、函数或 显式的函数模板 声明为静态或,
      — 一个物体或 明确声明的引用 const 且均未明确声明 extern 之前也没有声明过 外部链接;或
      — 数据成员 一个匿名工会的成员。

      【讨论】:

      • 请注意,此原始示例中的const 是“二级”const,适用于通过引用引用的对象。它不适用于引用本身(事实上,即使尝试这样做也是非法的)。这意味着即使您所说的是正确的,在原始示例中 externconst 无关。即使没有extern,该引用声明也会有外部链接。
      【解决方案5】:

      除此之外,这几乎可以肯定是对引用的滥用。引用旨在用作函数参数和返回值。您可以创建“引用变量”(我不知道如何描述它们)这一事实似乎是 C++ 语法的一个意外。是的,你可以和他们耍花招,但不,你不应该。

      底线 - 如果你有一个不是参数或返回值的引用,你可能做错了什么。除非你真的,真的知道你在做什么,在这种情况下你不会在这里问它,对吗?

      【讨论】:

      • 对此我不确定。参考数据成员呢?我经常使用它们。
      • Butterworth: 呃...我看不出使用带有运行时绑定的局部引用变量有什么问题,例如SomeType &r = <some condition> ? <lvalue1> : <lvalue2>;(然后继续使用r)。这是一种广泛使用且非常有用的技术,除非您要说必须为此目的使用 指针
      • @Andrey SomeType &r = <some condition> ? <lvalue1> : <lvalue2>; 好吧,我想我从来没有写过那种代码。一个真实的例子可能会说明为什么会这样。
      • Butterworth:这就像让我想出一个使用if 语句的例子......我很难做到这一点,因为语言功能是如此通用 i> 试图为它制作一个具体的例子感觉完全没有意义。假设我有一段代码可以使用左值a 或左值b(取决于某些条件)。所以,我会这样写:为ab(取决于条件)创建一个运行时别名r,然后使用r。举个例子吧?
      【解决方案6】:

      使用extern 表示该对象未在此处定义,而是在其他地方定义。

      【讨论】:

        猜你喜欢
        • 2011-06-13
        • 2020-01-05
        • 1970-01-01
        • 1970-01-01
        • 2020-07-29
        • 2020-01-14
        • 1970-01-01
        • 2018-11-12
        相关资源
        最近更新 更多