#include <iostream>
#include <cstring>
int main() {
std::cout << std::strlen("puzzled") << std::endl; // ❌ 編譯錯誤:'strlen' is not a member of 'std'
return 0;
}
但加上 using namespace std; 即可編譯通過。
| 頭文件 | C 風格名 | C++ 標準規定 |
|---|---|---|
<string.h> | strlen | **全局命名空間** 可用(兼容 C) |
<cstring> | strlen | **std 命名空間** 可用,**全局命名空間 可選** |
C++ 標準(ISO/IEC 14882)規定:
C++ 標準庫頭文件(如
<cstring>)將對應 C 庫函數放入std命名空間。**是否同時放入全局命名空間,屬於實現定義(implementation-defined)**。
<cstring> **不**將 strlen 注入全局命名空間 → 必須用 std::strlen 或 using namespace std;。std 和全局命名空間 → ::strlen 和 std::strlen 皆可用。using namespace std; 就能編過?因為 using namespace std; 將 std 中的所有符號引入當前作用域(通常是全局),使得非限定名 strlen 能找到 std::strlen。
// ✅ 推薦:顯式 std:: 前綴,編譯器無關、意圖清晰
#include <cstring>
#include <iostream>
int main() {
std::cout << std::strlen("puzzled") << std::endl;
return 0;
}
// ❌ 不推薦:污染全局命名空間,掩蓋潛在衝突
// using namespace std;
<iostream> 不需要 std:: 也能用 cout?因為示例中寫的是 std::cout。若寫 cout 直接報錯,同理需 using namespace std; 或 using std::cout;。
<cstring> 保證 std::strlen 存在,**不保證** ::strlen 存在。std::strlen 必加 std::。std::strlen**,代碼可移植、無歧義、符合現代 C++ 風格指南。這不是 Bug,是標準賦予編譯器的自由度。顯式限定名,一勞永逸。