作者loveme00835 (发箍)
看板C_and_CPP
标题Re: [问题] initializer 的具体作用
时间Sat May 2 20:11:00 2020
※ 引述《justhere (发废文就是生活的小确幸)》之铭言:
: 各位好,小弟新手,
: 目前在看C++ primier fifth edition,
: 进度到variable的定义与宣告这个小节,
: 在讲extern 这个keyword时书中举一个小范例:
: extern int i; // declares but does not define i
: int j; // declares and defines i
: 他解释
: To obtain a declaration that is not also a definition,
: we add extern keyword and may not provide an explicit initializer
: 请问具体来说c++中initializer所做的事情是什麽呢?
: 是分配记忆体位置和值给该name吗?
: 感谢
先不管
extern, 在语法上
int i;
这样写就是宣告. 而对於
非函式
的宣告来说, 即使我们可以不写 initializer, 但物件一定得经过
初始化, 而依照这个物件被宣告的地方, 会有不同的初始化行为,
有 static storage 如全域
int 物件, 就会经过 zero-initializ-
ation
(效果等同於 = 0, 和 memset(&obj, 0, sizeof(obj)) 意义
不同), 如果是区域
int 物件则不给初始值; 但
无论给不给初始值,
物件被宣告的当下, 它的实体即存在於该 TU (translation unit)
里 (这个结果才是书中说的定义)
在宣告前方加上
extern 修饰符语意就变了, 这时不为了创造物件
实体, 而是想
在当下能重复使用某处宣告过的物件 (可以存在同个
TU 或别的 TU), 而跨 TU 存取的情况下, 这个物件必须要具备
external linkage 才行. 考虑以下程式码, 请问印出的 i 值是多
少?
// translation unit #1
static int i =
1;
namespace ns {
int i =
2;
}
// translation unit #2
void foo() {
extern int i;
// declare i but i is not defined in foo()
std::cout <<
"i = " << i << std::endl;
}
以上是陷阱题, 在 TU #2 里面虽然预期会有个 i 宣告在全域底下
, 结果因为在 TU #1 里全域的 i 宣告有加上
static 修饰符所以
无法在别的 TU 里使用. 这段程式码会造成连结错误.
加了
extern 的宣告还是有办法回复原本宣告的功能, 只要明确地
用 initializer 初始化即可; 但是这样写语意是
矛盾的, 通常编译
器会给警告
(这时候会忽略 extern 修饰符).
除了
函式会特别把宣告还有建立实体分成两种写法, non-inline
static data member 也是如此:
class foo {
static int i;
// declare here
};
int foo::i =
1;
// define here
这时候我们不会说
static int i; 是定义: 它还是宣告, 但真正建
立实体的动作必须从 class definition 拉出来写在命名空间内.
最後来总结几个重点:
1. 宣告或定义要看情境, 不是单纯用语法来分辨
2. 加
extern 修饰符也可定义物件
3.
extern 是用来存取具有 external linkage 的物件
(跨 TU)
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.193.76.216 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/C_and_CPP/M.1588421464.A.70F.html
※ 编辑: loveme00835 (123.193.76.216 台湾), 05/03/2020 00:44:31