Skip to content

auto章节汉化 #24

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 112 additions & 120 deletions src/auto.cpp
Original file line number Diff line number Diff line change
@@ -1,138 +1,130 @@
/**
* @file auto.cpp
* @author Abigale Kim (abigalek)
* @brief Tutorial code for usage of the auto keyword.
* @brief 使用 auto 关键字的教程代码。
*/

// Includes std::cout (printing) for demo purposes.
// 引入 std::cout(用于输出)用于演示目的。
#include <iostream>
// Includes the std::set library.
// 引入 std::set 库。
#include <set>
// Includes the C++ string library.
// 引入 C++ 字符串库。
#include <string>
// Includes the std::vector library.
// 引入 std::vector 库。
#include <vector>
// Includes the std::unordered map library.
// 引入 std::unordered_map 库。
#include <unordered_map>

// The C++ auto keyword is a keyword that tells the compiler to infer the type
// of a declared variable via its initialization expression. It can be
// incredibly useful, as it allows for developer efficiency (where the developer
// no longer has to type out long, unruly type names). It is also useful in the
// context of for-each loops. However, using auto poses a risk where the
// developer may not be aware of the types they are using, and therefore at risk
// for buggy and non functional code. So be careful!

// Basic templated class with very long name, to show the usefulness of auto.
template <typename T, typename U> class Abcdefghijklmnopqrstuvwxyz {
public:
Abcdefghijklmnopqrstuvwxyz(T instance1, U instance2)
: instance1_(instance1), instance2_(instance2) {}

void print() const {
std::cout << "(" << instance1_ << "," << instance2_ << ")\n";
}

private:
T instance1_;
U instance2_;
// C++ 的 auto 关键字是一种告诉编译器通过初始化表达式来推断变量类型的关键字。
// 它非常有用,可以提高开发效率(开发者不再需要写出冗长、复杂的类型名)。
// 在 for-each 循环中也很有用。
// 但是,使用 auto 存在风险 —— 开发者可能不清楚自己正在使用的类型,
// 从而容易写出有 bug 或无法正常工作的代码。因此请小心使用!

// 一个带模板参数且名字非常长的基本类,用来展示 auto 的好处。
template <typename T, typename U>
class Abcdefghijklmnopqrstuvwxyz {
public:
Abcdefghijklmnopqrstuvwxyz(T instance1, U instance2)
: instance1_(instance1), instance2_(instance2) {}

void print() const {
std::cout << "(" << instance1_ << "," << instance2_ << ")\n";
}

private:
T instance1_;
U instance2_;
};

// Templated function that returns an object of this class with a very long
// name.
// 一个模板函数,返回该类的对象(类名非常长)。
template <typename T>
Abcdefghijklmnopqrstuvwxyz<T, T> construct_obj(T instance) {
return Abcdefghijklmnopqrstuvwxyz<T, T>(instance, instance);
return Abcdefghijklmnopqrstuvwxyz<T, T>(instance, instance);
}

int main() {
// The auto keyword is used to initialize the variable a. Here, the type
// is inferred to be type int.
auto a = 1;

// Here are more examples of using auto to declare basic variables.
// Depending on the IDE being used, it might say what types a, b, and c
// are.
auto b = 3.2;
auto c = std::string("Hello");

// auto is not particularly useful for these prior examples. As one can
// see, typing int a = 1;, float b = 3.2;, and std::string c = "Hello";
// does not take significant overhead. However, there will definitely
// be cases where the type name is long and complicated, or when the
// type name is heavily templated, and using auto may be helpful.
Abcdefghijklmnopqrstuvwxyz<int, int> obj = construct_obj<int>(2);
auto obj1 = construct_obj<int>(2);

// Maybe for one line it does not seem all that convenient, but imagine
// if using a class with a very long name was useful in the code for
// an extended period of time. Then, I'd imagine it would save a lot of
// typing time!

// One important thing to note about the auto keyword is that it
// defaults to copying objects, which can lower performance. Take the
// following example where we construct a int vector, and want to
// define a variable that is a reference to it.
std::vector<int> int_values = {1, 2, 3, 4};

// The following code deep-copies int_values into copy_int_values,
// since auto infers the type as std::vector<int>, not std::vector<int>&.
auto copy_int_values = int_values;

// However, the following code defines ref_int_values, which is a reference
// to int_values, and therefore does not deep copy the int_values vector.
auto& ref_int_values = int_values;

// The auto keyword is also useful for iterating through C++ containers.
// For instance, let's construct an unordered map with std::string keys
// and int values, and discuss methods of iterating through it.
std::unordered_map<std::string, int> map;
map.insert({{"andy", 445}, {"jignesh", 645}});

// One method mentioned in unordered_map.cpp was to iterate through
// a map by using a for loop with an iterator. Compare the readability
// of the two loops below.
std::cout << "Printing elements in map...\n";
for (std::unordered_map<std::string, int>::iterator it = map.begin();
it != map.end(); ++it) {
std::cout << "(" << it->first << "," << it->second << ")"
<< " ";
}
std::cout << std::endl;

std::cout << "Printing elements in map with auto...\n";
for (auto it = map.begin(); it != map.end(); ++it) {
std::cout << "(" << it->first << "," << it->second << ")"
<< " ";
}
std::cout << std::endl;

// It is also possible to use the auto keyword to iterate over vectors
// and sets.
std::vector<int> vec = {1, 2, 3, 4};
std::cout << "Printing elements in vector with auto...\n";
for (const auto& elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;

std::set<int> set;
for (int i = 1; i <= 10; ++i) {
set.insert(i);
}

std::cout << "Printing elements in set with auto...\n";
for (const auto &elem : set) {
std::cout << elem << " ";
}
std::cout << std::endl;

// Overall, auto is a useful C++ keyword that can be used to write code more
// efficiently, and to write cleaner and more readable code.
// Keep in mind that using auto to iterate through C++ containers is better
// in practice, since it produces more readable code. However, if you're not
// sure of the types that are being used, it is always okay to revert back
// to figuring out the type yourself.

return 0;
}
// 使用 auto 关键字初始化变量 a。这里,类型会被推断为 int。
auto a = 1;

// 下面是使用 auto 声明基本变量的更多示例。
// 根据使用的 IDE 不同,它可能会显示 a、b、c 的推断类型。
auto b = 3.2;
auto c = std::string("Hello");

// 对于上述示例来说,auto 并不是特别有用。
// 正如你所见,直接写 int a = 1;、float b = 3.2;、
// std::string c = "Hello"; 并不会带来太大负担。
// 但在类型名很长或模板嵌套复杂时,auto 就很有用了。
Abcdefghijklmnopqrstuvwxyz<int, int> obj = construct_obj<int>(2);
auto obj1 = construct_obj<int>(2);

// 也许一行代码看不出 auto 的优势,
// 但如果你需要频繁使用这种名字很长的类,那么 auto 将极大减少输入量!

// 关于 auto 的一个重要注意点是:
// 默认情况下 auto 会复制对象,这可能会影响性能。
// 下面这个例子中我们构造了一个 int 类型的 vector,
// 并想定义一个引用它的变量。

std::vector<int> int_values = {1, 2, 3, 4};

// 下面这行代码会将 int_values 深拷贝到 copy_int_values 中,
// 因为 auto 推断的类型是 std::vector<int>,不是引用 std::vector<int>&。
auto copy_int_values = int_values;

// 但是下面这行代码定义了 ref_int_values,它是 int_values 的引用,
// 所以不会深拷贝 vector。
auto& ref_int_values = int_values;

// auto 关键字在遍历 C++ 容器时也非常有用。
// 例如,我们构造一个 unordered_map,键为 std::string,值为 int,
// 然后看看不同的遍历方式。

std::unordered_map<std::string, int> map;
map.insert({{"andy", 445}, {"jignesh", 645}});

// unordered_map.cpp 中提到的一种方式是使用 iterator 进行遍历。
// 比较下面两个循环的可读性。

std::cout << "Printing elements in map...\n";
for (std::unordered_map<std::string, int>::iterator it = map.begin();
it != map.end(); ++it) {
std::cout << "(" << it->first << "," << it->second << ")"
<< " ";
}
std::cout << std::endl;

std::cout << "Printing elements in map with auto...\n";
for (auto it = map.begin(); it != map.end(); ++it) {
std::cout << "(" << it->first << "," << it->second << ")"
<< " ";
}
std::cout << std::endl;

// 也可以使用 auto 来遍历 vector 和 set。
std::vector<int> vec = {1, 2, 3, 4};
std::cout << "Printing elements in vector with auto...\n";
for (const auto& elem : vec) {
std::cout << elem << " ";
}
std::cout << std::endl;

std::set<int> set;
for (int i = 1; i <= 10; ++i) {
set.insert(i);
}

std::cout << "Printing elements in set with auto...\n";
for (const auto& elem : set) {
std::cout << elem << " ";
}
std::cout << std::endl;

// 总的来说,auto 是 C++ 中一个非常实用的关键字,
// 可以帮助我们写出更高效、更整洁、更易读的代码。
// 实践中,使用 auto 来遍历容器会让代码更清晰。
// 但如果你不确定变量的实际类型,回退到显式声明也是完全没问题的。

return 0;
}