C++ using全解析
作者:CoderMeijun
一、using的三种用途
C++中的 using 关键字有三种主要用途:
| 用途 | 作用 | 示例 |
|---|---|---|
| 命名空间引入 | 引入命名空间或其中的成员 | using namespace std; |
| 类型别名 | 给类型起别名 | using int_ptr = int*; |
| 模板别名 | 给模板类型起别名 | template<class T> using Vec = vector<T>; |
二、using 命名空间引入
1. using 声明(引入单个成员)
引入命名空间中的单个成员,之后可以直接使用该成员,不用再加命名空间前缀。
#include <iostream>
int main() {
// 没用 using 之前,必须写 std::
std::cout << "Hello" << std::endl;
// 用 using 声明后,可以直接写 cout 和 endl
using std::cout;
using std::endl;
cout << "Hello" << endl; // 不需要 std::
// 其他没引入的成员,仍然需要 std::
int a;
std::cin >> a; // cin 没引入,还是要写 std::
return 0;
}说明:using std::cout; 的意思是“把 std 命名空间里的 cout 引入当前作用域,以后直接用 cout 就行”。只引入这一个,其他成员不受影响。
2. using 指令(引入整个命名空间)
引入整个命名空间,之后所有成员都可以直接使用。
#include <iostream>
using namespace std; // 引入整个 std 命名空间
int main() {
cout << "Hello" << endl; // 直接使用
int a;
cin >> a;
return 0;
}3. 使用建议
| 场景 | 建议 |
|---|---|
| 头文件 | ❌ 不要用 using namespace,用完全限定名(如 std::cout) |
| 源文件 | ✅ 可以用 using namespace,但优先用 using 声明 |
| 局部作用域 | ✅ 可以用 using namespace,不影响其他地方 |
4. 注意事项:避免二义性
namespace A {
void func() { cout << "A" << endl; }
}
namespace B {
void func() { cout << "B" << endl; }
}
using namespace A;
using namespace B;
int main() {
func(); // ❌ 错误:不知道调用 A::func 还是 B::func
}解决方法:
方法1:不用 using,直接用完整名字
A::func(); // 明确调用 A 的 func B::func(); // 明确调用 B 的 func
说明:最安全的方式,不会有任何歧义,推荐在头文件或大型项目中使用。
方法2:用 using 声明,只引入不冲突的成员
using A::func; // 只引入 A 的 func func(); // 调用 A::func B::func(); // B 的 func 还是写全名
说明:只引入需要的成员,减少命名空间污染,同时避免冲突。
方法3:在局部作用域使用
{
using namespace A;
func(); // 在这个大括号里,func 指 A::func
}
{
using namespace B;
func(); // 在这个大括号里,func 指 B::func
}说明:将 using namespace 限制在局部作用域,不同区域可以分别使用不同的命名空间,互不影响。
三、using 类型别名
C++11 引入了 using 作为类型别名的新语法,比传统的 typedef 更直观。
1. typedef 的用法
typedef unsigned int u_int; // 无符号整型 typedef char* pChar; // 字符指针 typedef int Array[10]; // 数组 typedef void (*pFun)(int, int); // 函数指针
2. using 类型别名
using u_int = unsigned int; // 无符号整型 using pChar = char*; // 字符指针 using Array = int[10]; // 数组 using pFun = void(*)(int, int); // 函数指针
3. 对比
| 类型 | typedef | using |
|---|---|---|
| 基本类型 | typedef unsigned int u_int; | using u_int = unsigned int; |
| 指针 | typedef char* pChar; | using pChar = char*; |
| 数组 | typedef int Array[10]; | using Array = int[10]; |
| 函数指针 | typedef void (*pFun)(int, int); | using pFun = void(*)(int, int); |
using 的优势:语法更直观,尤其是函数指针,using pFun = void(*)(int, int); 比 typedef 更容易理解。
4. 更多示例
using value_type = int; using pointer = int*; using const_pointer = const int*; using reference = int&; using const_reference = const int&;
四、using 模板别名(最大优势)
using 最大的优势是支持模板别名,而 typedef 不能。
1. 定义模板别名
template<class T, size_t N> using Array = T[N];
说明:Array 是一个模板别名,T 是元素类型,N 是数组大小。使用时只需指定这两个参数。
2. 使用示例
int main() {
Array<int, 5> ar; // int ar[5]
Array<int, 5> br; // int br[5]
Array<double, 5> dr; // double dr[5]
Array<int*, 10> par; // int* par[10]
return 0;
}说明:一次定义,多次使用。不同大小、不同类型的数组都可以用同一个模板别名。
3. 为什么 typedef 做不到?
// typedef 做不到!必须为每个类型单独写 typedef int Array_int_5[5]; typedef double Array_double_5[5]; // 无法模板化
原因:typedef 只能给具体的、已经确定的类型起别名。如果需要多种类型或大小的数组,只能重复写,无法模板化。
4. 实际应用场景
// 简化 STL 容器写法
template<class T>
using Vec = std::vector<T>;
int main() {
Vec<int> v; // 等价于 std::vector<int>
Vec<double> d; // 等价于 std::vector<double>
Vec<string> s; // 等价于 std::vector<string>
return 0;
}说明:每次写 std::vector<int> 太长了,用 Vec<int> 代替,代码更短。而且 Vec 是模板,可以生成任意类型的 vector。
五、完整示例
下面的代码演示了 using 的两种主要用法:类型别名和模板别名。
#include <iostream>
#include <vector>
using namespace std;
// 1. 类型别名:简化复杂类型
using UInt = unsigned int;
using PFunc = void(*)(int); // 函数指针类型
// 2. 模板别名:简化嵌套容器
template<class T>
using Vec2D = vector<vector<T>>; // 二维数组
void printInt(int x) {
cout << x << endl;
}
int main() {
// 类型别名使用
UInt a = 10; // unsigned int
PFunc f = printInt; // 函数指针
f(a);
// 不用模板别名:写法冗长
vector<vector<int>> m1 = {{1, 2}, {3, 4}};
// 用模板别名:写法简洁
Vec2D<int> m2 = {{1, 2}, {3, 4}}; // 等价于 vector<vector<int>>
for (auto& row : m2) {
for (auto x : row) {
cout << x << " ";
}
cout << endl;
}
return 0;
}示例说明:
- 类型别名:
UInt比unsigned int短,PFunc让函数指针更易读 - 模板别名:
Vec2D<int>比vector<vector<int>>短很多,嵌套层次越深优势越明显
六、总结
| 用法 | 语法 | 作用 |
|---|---|---|
| 命名空间引入 | using namespace std; | 引入整个命名空间 |
| using 声明 | using std::cout; | 引入单个成员 |
| 类型别名 | using u_int = unsigned int; | 给类型起别名 |
| 模板别名 | template<class T> using Vec = vector<T>; | 给模板起别名 |
注意:
- “命名空间引入”和“using 声明”是命名空间相关的用法
- “类型别名”和“模板别名”是类型别名相关的用法
- 它们虽然都叫
using,但功能完全不同
到此这篇关于C++ using全解析的文章就介绍到这了,更多相关C++ using内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
