ISO/IEC 14882:2011之条款3.1——声明与定义
3.1 声明与定义
1、一个声明(条款7)可以在一个翻译单元内引入一个或多个名字,或重新声明由先前的声明所引入的名字。如果这样的话,该声明指定了这些名字的解释和属性。一个声明也可以有以下效果:
——一个静态的断言(条款7)
——控制模板实例化(14.7.2)
——对属性的使用(条款7),以及
——无(在一个空声明的情况下)
2、一个声明是一个定义,除非它声明了一个函数并且不指定其函数体(8.4),它包含了extern指定符(7.1.1)或一个linkage-specification[注:出现在一个linkage-specification中的用圆括号闭合起来的declaration-seq内,并不影响一个声明是否为一个定义。](7.5)并且不包含一个初始化器和一个函数体。它在一个类定义(9.2,9.4)中声明一个静态数据成员,它是一个类名声明(9.1),它是一个opaque-enum-declaration(7.2),它是一个template-parameter(14.1),它是一个函数声明符中的parameter-declaration(8.3.5),该函数声明符不是一个function-declaration中的declarator,或者它是一个typedef声明(7.1.3),一个alias-declaration(7.1.3),一个using-declaration(7.3.3),一个static__assert-declaration(条款7),一个attribute-declaration(条款7),一个empty-declaration(条款7),或一个using-directive(7.3.4)。
[例:以下除了一个,全都是定义:
int a; // 定义a extern const int c = 1; // 定义c int f(int x) { return x+a; }// 定义f并定义x struct S {int a; int b;}; // 定义 S, S::a, 和S::b struct X { // 定义X int x; // 定义非静态数据成员x static int y; // 定义静态数据成员y X(): x(0) { } // 定义一个X的构造器 }; int X::y = 1; // 定义X::y enum { up, down }; // 定义up和down namespace N { int d; } // 定义N和N::d namespace N1 = N; // 定义N1 X anX; // 定义anX
而这些只是声明:
extern int a; // 声明a extern const int c; // 声明c int f(int); // 声明f struct S; // 声明S typedef int Int; // 声明Int extern X anotherX; // 声明anotherX using N::d; // 声明d
——例结束]
3、[注:在某些情况下,C++实现隐式地定义默认构造器(12.1),拷贝构造器(12.8),搬移构造器(12.8),拷贝赋值操作符(12.8),搬移赋值操作符(12.8),或析构器成员函数。 ——注结束][例:给出:
#include <string> struct C { std::string s; // std::string是标准库的类(条款21) }; int main() { C a; C b = a; b = a; }
实现将隐式地定义函数使得结构体C的定义等价于:
struct C { std::string s; C() : s() { } C(const C& x): s(x.s) { } C(C&& x): s(static_cast<std::string&&>(x.s)) { } // : s(std::move(x.s)) { } C& operator=(const C& x) { s = x.s; return *this; } C& operator=(C&& x) { s = static_cast<std::string&&>(x.s); return *this; } // { s = std::move(x.s); return *this; }
~C() { } };
——例结束]
4、[注:一个类名也可以用一个elaborated-type-specifier(7.1.6.3)来隐式声明。 ——注结束]
5、一个程序是不良形式的,如果任一对象的定义给了该对象一个不完整类型(3.9)。