auto
What problem does this section solve?
In C++, many type names are long, difficult to type, and easy to mistype, for example:
std::map<std::string, std::vector<int>>::const_iterator it = m.begin();
std::shared_ptr<MyClass> ptr = std::make_shared<MyClass>();
Allow the compiler to automatically deduce types for us, reducing verbose type declarations to make code cleaner and easier to maintain.
What is this feature?
The auto keyword tells the compiler: "Please help me automatically deduce the type of this variable based on the initialized value." It doesn't weaken type safety — the deduced type is determined at compile time, so it remains strongly typed.
C++ standard version
C++11 (basic usage), C++14 added auto for function return type deduction, and C++17 introduced auto for use in scenarios like structured bindings.
Required header files
No additional header files are required. auto is a language keyword.
Basic Syntax
auto 变量名 = 表达式; // 编译器根据表达式推导类型
const auto 变量名 = 表达式; // 推导后加 const
auto& 变量名 = 表达式; // 推导为引用类型
const auto& 变量名 = 表达式; // 推导为只读引用类型
Common Usage
|Usage|Explanation|Here is the translation of the provided Simplified Chinese Markdown fragment into natural American English, following all specified rules.
Example|
|:---|:---|:---|
|auto|Automatic value type deduction (loses references and const)|auto x = 42; → int|
|const auto|Derived as a read-only type.|const auto s = "hello";|
|auto&|Derived as reference (modifiable original value)|auto& x = vec[0];|
|const auto&|Derive as read-only reference (no copy, no modification)|const auto& x = get_value();|
|auto*|derived as a pointer|auto* p = &x;|
|decltype(auto)|Perfect forwarding with reference and cv-qualifier preservation (C++14)|decltype(auto) x = get_ref();|
When to use which type
auto The most commonly misunderstood aspect is: it doesn't "automatically become the type you want", but rather deduces according to fixed rules. Especially when encountering references, const, or function return values, you must clearly write out your intent.
| Scene | Recommended Writing Style | Reason |
|---|---|---|
| The local variable types are very obvious. | auto x = expr; | Avoid redundant types. |
| Traverse large objects in read-only mode. | const auto& x | Avoid copying, and do not allow modification |
| Modify the original object | auto& x | Get the citation. |
| nullable pointer | auto* p = get(); | Let the reader see at a glance that this is a pointer. |
| Functions return references and must retain references | decltype(auto) | auto will lose its reference. |
| The type itself carries business meaning. | Explicit Type | For example Meter distance = ... is clearer than auto distance |
Example code
Example 1: Basic Type Inference
#include <iostream>
#include <string>
int main()
{
auto n = 42; // int
auto d = 3.14; // double
auto c = 'A'; // char
auto s = "hello"; // const char*
auto str = std::string("world"); // std::string
std::cout << "n = " << n << "\n";
std::cout << "d = " << d << "\n";
std::cout << "c = " << c << "\n";
std::cout << "str = " << str << "\n";
return 0;
}
Results:
n = 42
d = 3.14
c = A
str = world
Example 2: Building on Example 1, the difference between auto& and const auto&.
#include <iostream>
int main()
{
int x = 10;
auto a = x; // a 是 int,拷贝了 x
auto& b = x; // b 是 int&,是 x 的引用
const auto& c = x; // c 是 const int&,只读引用
a = 100;
std::cout << "after a=100, x = " << x << "\n"; // x 不变
b = 200;
std::cout << "after b=200, x = " << x << "\n"; // x 变了
// c = 300; // ❌ 编译错误!c 是只读引用
return 0;
}
Results:
after a=100, x = 10
after b=200, x = 200
Example 3: Building on Example 2, use auto to simplify iterators and complex types
Using auto in C++ allows the compiler to deduce types automatically, which significantly reduces verbosity when working with complex types like iterators or deeply nested container types. Here’s how it simplifies the code from Example 2:
Example 2 (without auto):
std::map<std::string, std::vector<int>>::iterator it = myMap.begin();
while (it != myMap.end()) {
std::vector<int> vec = it->second;
for (std::vector<int>::iterator vecIt = vec.begin(); vecIt != vec.end(); ++vecIt) {
std::cout << *vecIt << std::endl;
}
++it;
}
Example 3 (with auto):
auto it = myMap.begin();
while (it != myMap.end()) {
auto vec = it->second;
for (auto vecIt = vec.begin(); vecIt != vec.end(); ++vecIt) {
std::cout << *vecIt << std::endl;
}
++it;
}
Key improvements:
- Iterator declarations become
auto it = container.begin()instead of spelling out the full type. - Complex nested types (like
std::vector<int>::iterator) are inferred automatically. - Code becomes more readable and less error-prone, especially when types are long or change.
- The underlying logic remains identical—
autoonly simplifies the syntax, not the behavior.
This is especially useful when working with templated or generic code where exact types might be cumbersome to write out explicitly.
#include <iostream>
#include <vector>
#include <map>
#include <memory>
#include <string>
int main()
{
std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
// 不用 auto 的写法(类型名很长)
for (std::vector<std::string>::const_iterator it = names.begin();
it != names.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << "\n";
// 用 auto 简化(同样清晰)
for (auto it = names.begin(); it != names.end(); ++it)
{
std::cout << *it << " ";
}
std::cout << "\n";
// 智能指针用 auto 简化
auto ptr = std::make_shared<int>(42);
std::cout << "*ptr = " << *ptr << "\n";
return 0;
}
Results:
Alice Bob Charlie
Alice Bob Charlie
*ptr = 42
Example 4: Note copying vs referencing when using auto to iterate over containers
#include <iostream>
#include <vector>
#include <string>
int main()
{
std::vector<std::string> names = {"Alice", "Bob", "Charlie"};
// ❌ 错误用法:auto 会拷贝每个元素(低效)
std::cout << "auto (copies): ";
for (auto s : names)
{
s = "X"; // 修改的是拷贝,不影响原容器
}
for (auto s : names)
{
std::cout << s << " ";
}
std::cout << "(unchanged)\n";
// ✅ 正确用法:auto& 修改原容器中的元素
for (auto& s : names)
{
s = "X";
}
std::cout << "auto& (references): ";
for (auto s : names)
{
std::cout << s << " ";
}
std::cout << "(modified)\n";
return 0;
}
Results:
auto (copies): Alice Bob Charlie (unchanged)
auto& (references): X X X (modified)
Example 5: The difference between auto return value and decltype(auto) in Example 4
#include <iostream>
int global_score = 80;
int& score_ref()
{
return global_score;
}
// auto 作为函数返回类型时,会按"值"返回,引用会被丢掉
auto read_score()
{
return score_ref();
}
// decltype(auto) 会保留 score_ref() 的 int& 返回类型
decltype(auto) borrow_score()
{
return score_ref();
}
int main()
{
auto a = score_ref(); // a 是 int,拷贝
a = 90;
std::cout << "after auto a = 90, global_score = " << global_score << "\n";
auto& b = score_ref(); // b 是 int&,引用
b = 90;
std::cout << "after auto& b = 90, global_score = " << global_score << "\n";
auto c = read_score(); // c 是 int,read_score 本身也返回拷贝
c = 100;
std::cout << "after auto c = 100, global_score = " << global_score << "\n";
decltype(auto) d = borrow_score(); // d 是 int&,仍然引用 global_score
d = 100;
std::cout << "after decltype(auto) d = 100, global_score = " << global_score << "\n";
return 0;
}
Results:
after auto a = 90, global_score = 80
after auto& b = 90, global_score = 90
after auto c = 100, global_score = 90
after decltype(auto) d = 100, global_score = 100
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 Deduction | auto x = 表达式 | In the simplest case, the type is determined by the initialization value. | String literal is inferred as const char* |
| Example 2 | auto vs auto& vs const auto& | auto&、const auto& | auto will lose references and top-level const; you must use auto& to reference the original variable. | Be careful when iterating through container elements. |
| Example 3 | Simplify complex types | Use auto with iterators and smart pointers | 当类型名过长时,可使用 auto 关键字保持代码的可读性。例如: |
// 不推荐:冗长的类型声明
std::vector<std::pair<int, std::string>>::iterator it = myVector.begin();
// 推荐:使用 auto
auto it = myVector.begin();
这样不仅使代码更简洁,还能在类型变更时减少维护成本。|auto doesn't weaken type safety; it just helps the compiler write the code for you.|
|Example 4|The copy trap of auto during iteration|Range-based for loops combined with auto or auto& in C++|Traverse and copy elements, auto& reference elements|To modify the original container, you must use auto&.|
|Example 5|auto returns value vs decltype(auto)|auto function return, decltype(auto)|When a function returns a reference, a normal auto will degrade to a value return.|decltype(auto) is quite powerful, but also make sure it won't return a dangling reference.|
Common Errors
Error 1: Thought that auto could automatically infer as a reference.
int x = 10;
auto y = x;
y = 20; // x 不会变!y 是拷贝不是引用
Correct approach: The original variable needs to be modified using auto&.
Error 2: Using auto to declare function parameters
void func(auto x) { ... } // C++20 之前是错误!(除非是泛型 lambda)
Correct approach: ordinary function parameters cannot use auto (C++20 allows it, but that's template syntax).
Error 3: auto cannot be used in a multi-variable declaration
auto x = 1, y = 3.14; // ❌ 编译错误!推导类型不一致
The correct approach: each auto variable is declared separately.
Error 4: Overusing 'auto' makes the business meaning disappear
auto timeout = 3000; // 3000 是毫秒?秒?次数?
The correct approach: Types or names should convey meaning. For example, std::chrono::milliseconds timeout{3000};, or at least auto timeout_ms = 3000;.
使用建议
- 明确目标:在开始前确定您的具体需求,以便选择最合适的工具或教程。
- 充分利用资源:参考官方文档、教程和博客,这些资料能帮助您快速上手并解决问题。
- 实践应用:通过动手操作项目或编写代码来巩固学习成果,提升实际操作能力。
- 问题解决:遇到困难时,查阅参考资料或寻求社区支持,逐步培养独立解决问题的能力。
- 分享经验:完成项目后,可以撰写文章或博客分享心得,帮助其他学习者。
如果需要针对特定领域(如单片机、机器人或环境搭建)的进一步建议,请提供更多信息,我将为您细化内容。
- Use auto wherever possible: reduce repetitive type declarations to make the code more concise.
- Iterate over containers using
const auto&(without modification) orauto&** (needs modification), to avoid accidental copying. - Places that clearly need references must include
auto&:autowill not automatically infer references. autocannot fully replace explicit types: When types are not obvious (such as inferring from a function's return value), writing types explicitly might be clearer.decltype(auto)should only be used when the reference truly needs to be preserved: it is more precise and makes it easier to expose dangling references.
Summary
autoallows compilers to automatically infer variable types, reducing the need for verbose type declarations.autoloses references and top-level const; to traverse a container, useconst auto&orauto&.- This is particularly suited for simplifying complex types such as iterators and smart pointers.
autofunctions return by value by default; in order to preserve reference semantics, usedecltype(auto).autois still strongly typed, and its type is determined at compile time.