输入和输出
iostream标准库
C++标准库<iostream>,包含了两个基础类型istream和ostream,分别表述输入流和输出流,一个流就是一个字符序列。
cin是istream的的对象;cout,cerr,clog是ostream的对象。cin和cout是标准输入和输出,cerr是输出警告和错误消息,clog是输出程序运行的一般信息。
std::cout << "hello world" << std::endl;
<<运算符左右两侧是两个变量,一个是ostream的对象cout,一个是字符串变量,<<将字符串变量写到了ostream对象中,返回cout这个结果。然后继续计算cout << std::endl;这个语句,将操纵符endl写入cout中,(endl的作用是结束当前行,并将缓冲区刷新到控制台,也就是说cout接收变量不会马上打印,而是存储在缓冲区,当遇到endl时会刷新缓冲区,而‘\n’只有换行效果,没有刷新缓冲区效果。或者使用std::cout.flush()去刷新缓冲区)。
读取数量不定的输入数据
while (std::cin >> value) {
sum += value;
}
C++11 functional
C++11 引入了 <functional> 标准库头文件,其中包含了一些有关函数对象(function objects)和函数指针的实用工具,以支持更灵活的函数编程和泛型编程。这个库引入了一些重要的类和概念,让函数处理更加方便和类型安全。下面是一些重要的 <functional> 组件和概念:
std::function:std::function 是一个通用的函数包装器,允许将可调用对象(函数、函数指针、成员函数指针等)封装为一个对象,以便能够像普通函数一样进行传递和调用。这对于实现回调函数或参数化函数的目的非常有用。
函数对象(Function Objects):C++中的函数对象是可调用对象,通常是类的实例,实现了函数调用运算符 operator()。C++11 引入了 std::function 之后,函数对象变得更加通用和易于使用。
std::bind:std::bind 允许创建一个函数对象,将参数绑定到函数的参数。这在创建局部函数或用于回调的函数时非常有用,允许你事先绑定一些参数并稍后调用函数。
Lambda 表达式:C++11 引入了 Lambda 表达式,它们允许在代码中内联定义匿名函数。Lambda 表达式使得函数式编程风格更加容易,可以在循环、算法中使用,也可以用作回调函数。
#include <iostream>
#include <functional>
int main() {
std::function<int(int, int)> add = [](int a, int b) { return a + b; };
auto multiply = std::bind([](int a, int b) { return a * b; }, std::placeholders::_1, 5);
std::cout << "Add: " << add(3, 4) << std::endl;
std::cout << "Multiply: " << multiply(3) << std::endl;
return 0;
}
C++11 lamada表达式
用于创建匿名函数,通常用于短期、一次性的函数需求。Lambda 表达式的主要目的是以一种更简洁的方式定义函数,通常用于 STL 算法、回调函数和函数式编程。
Lambda 表达式的一般语法如下:
[capture_clause](parameter_list) -> return_type {
// 函数体
}
capture_clause:用于指定 Lambda 表达式中的变量捕获方式。可以通过值捕获([=])、引用捕获([&])、或特定变量捕获([var])等方式来访问外部作用域中的变量。
parameter_list:Lambda 表达式的参数列表,类似于普通函数的参数。
return_type:可选项,用于指定 Lambda 表达式的返回类型。如果忽略,编译器通常能够根据返回语句自动推断返回类型。
函数体:包含 Lambda 表达式的具体操作,与普通函数体类似。
Lambda 表达式的一个示例:
#include <iostream>
int main() {
int x = 5;
int y = 10;
// Lambda 表达式,以值捕获 x 和 y
auto add = [x, y]() {
return x + y;
};
// 调用 Lambda 表达式
int result = add();
std::cout << "Result: " << result << std::endl;
return 0;
}
在这个示例中,Lambda 表达式 add 捕获了 x 和 y 的值,并返回它们的和。Lambda 表达式允许你在其内部使用外部变量,并以不同的捕获方式操作这些变量,使得代码更加紧凑和易读
C++11 auto
auto 是 C++11 引入的关键字,用于自动推断变量的类型。它使编程更加方便,减少了需要显式指定变量类型的需求,特别是在处理复杂的数据类型或使用泛型编程时非常有用。
auto i = 42; // 推断 i 为整数类型
auto name = "John"; // 推断 name 为字符串类型
std::vector<int> numbers = {1, 2, 3, 4, 5};
for (auto it = numbers.begin(); it != numbers.end(); ++it) {
// 使用 auto 推断的迭代器类型
std::cout << *it << " ";
}
C++11 move
move 是 C++11 引入的关键字,用于实现移动语义,特别是在处理对象的所有权转移和提高性能方面非常有用。它通常与右值引用 (&&) 结合使用。
关键点和用途包括:
移动语义:move 关键字允许将资源(例如动态分配的内存或文件句柄)的所有权从一个对象转移到另一个对象,而不进行深拷贝。这可以显著提高性能,特别是在处理大型数据结构时。
右值引用:通常,move 与右值引用结合使用,右值引用用于标识临时对象或可以"偷窃"资源的对象。这是因为只有右值引用能够与 move 结合使用,以表示移动语义。
int x = 42;
int y = std::move(x); // 使用 move 将 x 的值转移到 y,x 变为未定义状态
避免不必要的拷贝:move 通常用于避免不必要的对象拷贝,从而提高性能。它可以用于标记对象可以"偷窃"资源而不进行深拷贝的情况。
标准库中的应用:C++标准库中的许多容器和类型都利用了移动语义,例如 std::vector 的 push_back,std::unique_ptr,std::string 等。
std::vector<int> source = {1, 2, 3};
std::vector<int> destination = std::move(source); // 使用 move 将 source 所有权转移到 destination,source 变为未定义状态,移动后source不可再进行访问
右值引用,左值引用,完美引用
左值引用(Lvalue Reference):
- 左值是表达式的结果是一个具名对象,通常是一个变量的名称。
- 左值引用用于引用左值,通常表示对对象的可修改引用。
- 左值引用使用单个&符号来定义,如 int& ref = x;,其中 ref 是对 x 的左值引用。
右值引用(Rvalue Reference):
- 右值是表达式的结果是一个临时值或不具名的值,通常是表达式的计算结果。
- 右值引用用于引用右值,通常表示对可以"偷窃"资源的引用,例如移动语义。
- 右值引用使用双&&符号来定义,如 int&& rref = 5;,其中 rref 是对 5(右值)的右值引用。
完美引用(Perfect Forwarding):
- 完美引用是C++11引入的特性,它是右值引用和模板的结合,允许在函数模板中以一种通用的方式传递参数。
- 完美引用通常在泛型编程中使用,允许将参数引用传递给其他函数,同时保留原始参数的左值或右值属性。
- 完美引用通常通过std::forward函数来实现,它将参数的引用类型传递给其他函数。