C++中declaration与define的区别

看过不少C++的书籍里都没有明确地指出处声明(declaration)与定义(define)的区别,或者只是提到了需要支持分离式编译,使用extern specifier的就是声明,不带的就是定义。实际上我觉得C++标准中对于声明(declaration)与定义(define)的区别描述的更为清晰。

《C++ Primer 5th》中2.2.2节提到变量声明与定义的关系:

为了支持分离式编译,C++语言将声明和定义区分开来。声明(declaration)**使得名字为程序所知,一个文件如果想使用别处定义的名字则必须包含那个名字的声明。而定义(define)**负责创建与名字相关联的实体。
如果想要声明一个变量而非定义它,就在变量名前面添加关键字extern,而且不要显式地初始化变量。

1
2
extern int i; // 声明i而非定义i
int j; // 申明并定义i

任何包含了显式初始化的声明即成为定义。我们能给extern关键字标记的变量一个初始值,但这么做就抵消了extern的作用。extern语句如果包含初始值就不再是声明,而变成定义了。

1
extern double pi=3.14159; // 定义

以上是C++ Primer中对于变量声明和定义的关系的描述。
我觉得C++标准的描述更全面一些:

A declaration is a definition unless:

  • it declares a function without specifying the function’s body (8.4),
  • it contains the extern specifier (7.1.1) or a linkage-specification (7.5) and neither an initializer nor a function- body,
  • it declares a static data member in a class definition (9.2, 9.4),
  • it is a class name declaration (9.1),
  • it is an opaque-enum-declaration (7.2),
  • it is a template-parameter (14.1),
  • it is a parameter-declaration (8.3.5) in a function declarator that is not the declarator of a function-definition,or
  • it is a typedef declaration (7.1.3),
  • an alias-declaration (7.1.3),
  • a using-declaration (7.3.3),
  • a static_assert-declaration (Clause 7),
  • an attribute- declaration (Clause 7),
  • an empty-declaration (Clause 7), or
  • a using-directive (7.3.4).

我来简单翻译一下。
一个声明是一个定义,除非

  • 声明一个函数但没有指定函数体
1
int func(); // 声明
  • 包含一个extern说明符或一个linkage-specification(e.g:extern “C”)且既没有一个初始化器也没有一个函数体。
1
2
extern int x;
extern "c" void func();
  • 在类定义的内部声明一个static数据成员。
1
2
3
4
5
6
7
struct A{
A(){};
static int x; // declaration
static const int y=11; // define
// notice: non-const static data member must be initialized out of line
};
int A::x=12; // define
  • 一个类名字声明。
1
struct A;
  • 一个opaque-enum-declaration(没想好这个要咋翻译)
1
enum A:int;
  • 一个模板形参(template parameter)
1
template<typename T> T f(T); //T is a decleration
  • 函数声明中的形参声明
1
int func(int x);
  • 一个typedef声明
1
typedef int INT;
  • 一个别名(alias)声明
1
using INT=int;
  • 一个using声明
1
2
3
4
5
namespace A{
typedef int INT;
}

using A::INT;
  • 一个static_assert声明
1
static_assert(foo());
  • 一个属性声明
1
[[noreturn]] void funv();
  • 一个空的声明
1
2
// empty-declaration:
;
  • 一个using指令
1
using namespace std;

在以上的十几种情况中,声明不是定义。简单地说,“声明”就是提供名字和参数等一些原型信息,而“定义”则是提供存储空间分配和相应的实现。
额,写完才发现cppreference上已经有:Define and ODR,郁闷…

全文完,若有不足之处请评论指正。

微信扫描二维码,关注我的公众号。

本文标题:C++中declaration与define的区别
文章作者:查利鹏
发布时间:2017年02月24日 21时09分
本文字数:本文一共有1.5k字
原始链接:https://imzlp.com/posts/21831/
许可协议: CC BY-NC-SA 4.0
文章禁止全文转载,摘要转发请保留原文链接及作者信息,谢谢!
您的捐赠将鼓励我继续创作!