C++高频知识点(五)
文章目录
- 21. 解释C++中的引用折叠规则
- 规则1:T& & 变为 T&
- 规则2:T& && 变为 T&
- 规则3:T&& & 变为 T&
- 规则4:T&& && 变为 T&&
- 22. 什么是完美转发?
- 23. #include<a.h> 与#include”a.h”的区别 规范
- 24. 讲讲STL的六大组件
- 25. vector push_back和emplace_back的区别
21. 解释C++中的引用折叠规则
规则1:T& & 变为 T&
这是最直观的规则,左值引用的左值引用最终折叠为原始类型的左值引用。这意味着当你有一个左值引用的左值引用时,它被折叠成原始类型的左值引用。
int x = 10;
int& &ref = x; // ref 的类型是 int&,折叠后就是 int&
规则2:T& && 变为 T&
当你有一个左值引用的右值引用时,它会折叠为左值引用。这意味着我们不能将一个左值引用绑定到右值引用上,而是要保持它作为左值引用。
int x = 10;
int& &&ref = x; // ref 的类型是 int&,折叠后就是 int&
规则3:T&& & 变为 T&
这是正确的引用折叠规则。当我们有一个右值引用的左值引用时,它折叠成左值引用。这意味着即使我们原本期望是一个右值引用(T&&),由于与左值引用结合,它会变成左值引用(T&)。在这种情况下,T&& 作为一个右值引用失去其右值引用的特性,被折叠为左值引用。
int x = 10;
int&& &ref = x; // ref 的类型是 int&,折叠后就是 int&
我们会将右值引用的左值引用折叠成左值引用 (T&& & → T&),这是因为 左值引用不能绑定到右值引用。具体来说,当我们传递右值引用(T&&)并将其绑定到左值引用时,C++ 编译器需要保证引用的类型仍然保持一致。所以即使我们传递的是右值引用,它会折叠成左值引用,而不是右值引用。
规则4:T&& && 变为 T&&
这是最常见的情况,两个右值引用合并时,仍然保留为右值引用。
int x = 10;
int&& &&ref = 10; // ref 的类型是 int&&,折叠后就是 int&&
22. 什么是完美转发?
完美转发(Perfect Forwarding)是C++11中引入的一种技术,用于将函数模板的参数精确地传递给另一个函数,而不改变参数的值类别(即左值或右值的属性)。它解决了在编写通用代码时,如何保持参数的值类别不变的问题。
下面是一个简单的例子来说明如何实现完美转发:
#include <iostream>
#include <utility> // std::forward// 确保在调用前声明 process 函数
void process(int& x);
void process(int&& x);// 接受一个通用的模板参数并转发
template<typename T>
void wrapper(T&& arg) {// 使用 std::forward 转发参数process(std::forward<T>(arg));
}void process(int& x) {std::cout << "Lvalue reference: " << x << std::endl;
}void process(int&& x) {std::cout << "Rvalue reference: " << x << std::endl;
}int main() {int a = 5;wrapper(a); // 传递一个左值wrapper(10); // 传递一个右值return 0;
}
在这个例子中,wrapper 函数使用了模板参数 T 的转发引用 T&&,并通过 std::forward 将参数 arg 转发给 process 函数。根据传递的参数是左值还是右值,std::forward 会相应地调用 process 的左值引用版本或右值引用版本。
这样,通过使用完美转发,可以确保参数的值类别在转发过程中保持不变,避免了不必要的拷贝或移动操作,提高了代码的效率和灵活性。
23. #include<a.h> 与#include”a.h”的区别 规范
24. 讲讲STL的六大组件
仿函数(Function Objects)是 C++ 中的一种重要特性。它指的是那些能够像普通函数一样被调用的对象。仿函数是通过重载类中的 operator() 运算符来实现的。与普通函数不同,仿函数不仅能存储数据(比如成员变量),还能够被传递和保存。
一个仿函数是一个类,该类重载了 operator() 运算符,使得该类的对象可以像函数一样被调用。例如:
#include <iostream>class Adder {
public:// 构造函数,初始化加法器的增量Adder(int x) : value(x) {}// 重载 operator(),使得对象可以像函数一样被调用int operator()(int y) const {return value + y; // 返回 value 和 y 的和}private:int value; // 存储加法器的增量
};int main() {Adder add5(5); // 创建一个增量为 5 的加法器std::cout << "5 + 3 = " << add5(3) << std::endl; // 使用仿函数,输出 8return 0;
}
类 Adder:定义了一个简单的加法仿函数。这个类有一个私有成员变量 value,它表示加法器的增量。Adder 类重载了 operator() 运算符,使得类的对象可以像函数一样被调用。
25. vector push_back和emplace_back的区别
std::vector 是 C++ 标准库中的一个动态数组,它提供了许多方法来添加、删除和访问其元素。
其中,push_back 和 emplace_back 是两种常用的添加元素到 std::vector 尾部的方法,但它们之间存在一些关键的区别。
std::vector<std::string> v;
v.emplace_back("Hello, World!"); // 直接在 v 的内存中构造一个 std::string 对象//再看下面这个例子
#include <vector>
struct obj
{obj(int, double) {}
};int main()
{std::vector<obj> v;v.emplace_back(1, 3.14); // obj in created in place in the vector
}
之后我会持续更新,如果喜欢我的文章,请记得一键三连哦,点赞关注收藏,你的每一个赞每一份关注每一次收藏都将是我前进路上的无限动力 !!!↖(▔▽▔)↗感谢支持!