using
What problem does this section solve?
In C, we use typedef to create an alias for a type. However, the syntax of typedef is quite awkward, especially when aliasing function pointers or templates—the notation is unintuitive and hard to read.
C++11 introduced alias declarations, which have cleaner syntax and support template aliases, something the older feature typedef can't do.
What is this feature?
There are two common uses for using:
- Type Alias: Giving a new name to an existing type, similar to
typedefbut with clearer syntax. - Template aliases: give alternate names to template types (which
typedefcannot do).
C++ standard version
C++11 (type alias syntax), C++11 template aliases.
Required header files
No additional header files are required. using is a language keyword.
Basic Syntax
// 类型别名
using 新名字 = 已有类型;
// 模板别名
template<typename T>
using 新名字 = 模板类型<T...>;
Comparison with typedef
| Scene | typedef | using |
|---|---|---|
| Primitive Types | typedef int Integer; | using Integer = int; |
| function pointer | typedef void (*Func)(int); | using Func = void(*)(int); |
| array | typedef int Arr10[10]; | using Arr10 = int[10]; |
| Template Alias | ❌ Not supported | using Vec<T> = std::vector<T>; |
Using can do:
- Simplify type names by creating aliases for namespaces and types.
- Bring names from a base class into a derived class scope.
Using cannot do:
- Replace the need for inheritance or virtual functions.
- Change the fundamental behavior of a class or its methods.
using creates a type alias, not a new type. It improves the readability of complex types but doesn't prevent you from mistakenly using two types that are fundamentally the same underneath.
| Requirement | Is it suitable to use | Explanation |
|---|---|---|
| Shorten complex type names | ✅ Suitable | using Callback = std::function<void(int)>; |
| Standardize business names in the project | ✅ Suitable | using UserId = int; make code more semantic |
| Simplified syntax for defining templates | ✅ Fits well | template<typename T> using Vec = std::vector<T>; |
| Preventing cross-contamination of different business types. | Understood, the instructions are noted. | using Meter = double; and using Second = double; are fundamentally still both doubles. |
| Create truly new types | Use struct / class / enum class | The compiler can help you check mixed use. |
Example code
Example 1: using basics — replace typedef
#include <iostream>
#include <string>
#include <vector>
// 旧写法(typedef)
typedef std::vector<int> IntVector1;
// 新写法(using)
using IntVector2 = std::vector<int>;
int main()
{
// 两种写法效果完全一样
IntVector1 v1 = {1, 2, 3};
IntVector2 v2 = {4, 5, 6};
std::cout << "v1: ";
for (int n : v1) std::cout << n << " ";
std::cout << "\n";
std::cout << "v2: ";
for (int n : v2) std::cout << n << " ";
std::cout << "\n";
return 0;
}
Results:
v1: 1 2 3
v2: 4 5 6
Example 2:Building on Example 1,using aliases for function pointers
#include <iostream>
// typedef 的函数指针写法(别扭)
typedef int (*FuncPtr1)(int, int);
// using 的函数指针写法(直观)
using FuncPtr2 = int (*)(int, int);
int add(int a, int b)
{
return a + b;
}
int multiply(int a, int b)
{
return a * b;
}
int main()
{
FuncPtr2 op1 = add;
FuncPtr2 op2 = multiply;
std::cout << "add(3, 5) = " << op1(3, 5) << "\n";
std::cout << "multiply(3, 5) = " << op2(3, 5) << "\n";
return 0;
}
Results:
add(3, 5) = 8
multiply(3, 5) = 15
Example 3: Building on Example 2, template aliases (which typedef can't achieve)
#include <iostream>
#include <vector>
#include <map>
#include <string>
// 模板别名:定义一个泛型的 vector
template<typename T>
using Vec = std::vector<T>;
// 模板别名:键为 string 的 map
template<typename T>
using StringMap = std::map<std::string, T>;
int main()
{
Vec<int> vi = {1, 2, 3};
Vec<double> vd = {1.1, 2.2, 3.3};
StringMap<int> scores = {{"Alice", 85}, {"Bob", 92}};
std::cout << "Vec<int>: ";
for (int n : vi) std::cout << n << " ";
std::cout << "\n";
std::cout << "Vec<double>: ";
for (double d : vd) std::cout << d << " ";
std::cout << "\n";
std::cout << "StringMap<int>: ";
for (const auto& p : scores)
std::cout << p.first << ":" << p.second << " ";
std::cout << "\n";
return 0;
}
Results:
Vec<int>: 1 2 3
Vec<double>: 1.1 2.2 3.3
StringMap<int>: Alice:85 Bob:92
Example 4: Building on Example 3, a using alias is not a new type.
#include <iomanip>
#include <iostream>
using Meter = double;
using Second = double;
double speed(Meter distance, Second time)
{
return distance / time;
}
struct MeterValue
{
double value;
};
struct SecondValue
{
double value;
};
double safe_speed(MeterValue distance, SecondValue time)
{
return distance.value / time.value;
}
int main()
{
Meter distance = 100.0;
Second time = 9.58;
std::cout << std::fixed << std::setprecision(2);
std::cout << "speed = " << speed(distance, time) << "\n";
// using 只是别名,下面这行语义错了,但编译器仍然允许
std::cout << "wrong order = " << speed(time, distance) << "\n";
MeterValue d{100.0};
SecondValue t{9.58};
std::cout << "safe speed = " << safe_speed(d, t) << "\n";
// safe_speed(t, d); // ❌ 编译错误:SecondValue 不能当 MeterValue 用
return 0;
}
Results:
speed = 10.44
wrong order = 0.10
safe speed = 10.44
runtime results
See the "running results" for each example above.
Key syntax explanation in the example
|Here is the translation of the provided Simplified Chinese Markdown fragment into natural American English, following all specified rules.
| Example | Discusses what | Newly emerged syntax | Why write it this way | Precautions |
|---|---|---|---|---|
| Example 1 | basic type aliases | using Name = Type; | The syntax is more intuitive, and the placeholder = makes it immediately clear that "alias = original type". | Also works, but using is more readable. |
| Example 2 | function pointer alias | using Func = int(*)(int,int); | A name in the middle reads more naturally than a typedef name sandwiched in between. | In actual projects, it is recommended to use std::function instead of raw function pointers. |
| Example 3 | Template Alias | template<T> using Vec = vector<T>; | typedef cannot do template aliasing; this is a unique ability of using. | Very suitable for simplifying nested template types |
| Example 4 | using is not a new type | using Meter = double, packaging structure | Aliases enhance readability, structures ensure type safety. | When parameter inversion needs to be prevented, do not rely solely on using. |
Common Errors
Error 1: The = direction of the using alias is reversed
using int = MyInt; // ❌ 方向反了!应该是 using 别名 = 原类型
Correct approach: using MyInt = int;
Error 2: Unrestricted use of using in header files
// 头文件中
using namespace std; // ❌ 污染全局/外部命名空间!
Correct approach: avoid using namespace in header files; only use them in .cpp implementation files or within functions.
Error 3: Confusion between using declarations and using aliases
using std::cout; // using 声明:引入名字
using MyVec = std::vector<int>; // using 别名:创建别名
These represent two distinct usages: the former introduces a name into the current scope, while the latter creates a type alias.
错误 4:误以为 using 能提供强类型检查
using UserId = int;
using ProductId = int;
void load_user(UserId id);
ProductId pid = 10;
load_user(pid); // 能编译,因为 UserId 和 ProductId 本质都是 int
Correct approach: If mixing must be prevented, use a wrapper type like struct UserId { int value; }; or use enum class to express a limited set.
使用建议
- 明确目标:在开始前确定您的具体需求,以便选择最合适的工具或教程。
- 充分利用资源:参考官方文档、教程和博客,这些资料能帮助您快速上手并解决问题。
- 实践应用:通过动手操作项目或编写代码来巩固学习成果,提升实际操作能力。
- 问题解决:遇到困难时,查阅参考资料或寻求社区支持,逐步培养独立解决问题的能力。
- 分享经验:完成项目后,可以撰写文章或博客分享心得,帮助其他学习者。
如果需要针对特定领域(如单片机、机器人或环境搭建)的进一步建议,请提供更多信息,我将为您细化内容。
- Replace
usingwithtypedef: The syntax is clearer and also supports template aliases. - Leverage template aliases to simplify code: for example,
using TaskMap = std::map<int, std::function<void()>>;. - Do not use
using namespacein header files: avoid namespace pollution. - The using declaration (
using std::cout) can be used in .cpp files or inside functions, simplifying the code. - Don’t just use using when you need strong typing: while using improves readability,
struct/class/enum classis what can change the type itself.
Summary
using NewName = OldType;is more intuitive thantypedefin terms of syntax.template<typename T> using Alias = ...;is a template alias that typedef cannot achieve.- Function pointer aliases and container type aliases are indeed practical in projects.
usingis just an alias, not a new type; when type safety is required, you need to introduce wrapper types.- Don't confuse
usingaliases withusingdeclarations (namespace introductions).