1、什么是STL? C++ STL从广义来讲包括了三类:算法,容器和迭代器。 算法包括排序,复制等常用算法,以及不同容器特定的算法。 容器就是数据的存放形式,包括序列式容器和关联式容
1、什么是STL?
C++ STL从广义来讲包括了三类:算法,容器和迭代器。
- 算法包括排序,复制等常用算法,以及不同容器特定的算法。
- 容器就是数据的存放形式,包括序列式容器和关联式容器还有容器适配器,序列式容器就是list,vector等,关联式容器就是set,map等,容器适配器就是stack,queue等。
- 迭代器就是在不暴露容器内部结构的情况下对容器的遍历。
2、trivial destructor是什么?
“trivial destructor”一般是指用户没有自定义析构函数,而由系统生成。
反之,如果用户自定义了析构函数,则称之为“non-trivial destructor”, 这种析构函数如果申请了新的空间一定要显式的释放,否则会造成内存泄漏。
3、使用智能指针管理内存资源,RALL是怎么回事?
RALL全称“Resource Acquisition is Initialization”,直译过来是“资源获取即初始化”,也就是说在构造函数中申请分配资源,在析构函数中释放资源。
因为C++的语言机制保证了,当一个对象创建的时候,自动调用构造函数,当对象超出作用域的时候,会自动嗲用析构函数。所有在RALL的指导下,我们应该使用类来管理资源,将资源和对象的生命周期绑定。
智能指针(std::shared_ptr和std::unique_ptr)即RALL最具代表的实现,使用智能指针,可以实现自动的内存管理,再也不用担心自己忘记delete,从而造成内存泄漏。
4、迭代器;++it、it++哪个好,为什么?
1、前置返回一个引用,后置返回一个对象
// ++i实现代码为:
int& operator++()
{
*this += 1;
return *this;
}
2、前置不会产生临时对象,后置必须产生临时对象,临时对象会导致效率降低
//i++实现代码为:
int operator++(int)
{
int temp = *this;
++*this;
return temp;
}
5、说一下C++左值引用和右值引用
语法和用法上的区别
1、左值引用
- 左值引用是对左值的引用,它使用‘&’符号声明。例
int x = 10;
int &ref = x;
- 左值是可以取地址的表达式,例如变量、函数返回的左值,表达式中的左值等。
- 左值引用主要用于修改被引用的对象,可以在引用上修改其值,并且生命周期会延长到引用的作用域结束。
- 左值引用不能绑定到右值(临时变量)。
int &x = 10;这样是不行的
2、右值引用
- 右值引用是对右值的引用,它使用‘&&’符号声明。例如
int && rref = 10;
- 右值是不能去地址的表达式,例如临时对象,常量、表达式中的右值等。
- 右值引用主要用于移动语义,允许将资源所有权从一个对象转移到另一个对象,避免不必要的资源拷贝,提高性能。
- C++11引入了移动语义和右值引用,使得支持C++的类能够对临时对象进行优化,例如通过移动构造函数将资源的所有权从临时对象转移到新创建的对象,而不是进行深度拷贝。
使用右值引用和移动语义可以显著提高性能,特别是在处理大型对象或资源管理类时,避免了不必要的拷贝构造和析构开销。同时,右值引用还支持了 C++ 中的移动语义语法,例如 std::move
函数可以将一个左值转换为右值引用,从而可以触发移动语义。需要注意的是,在使用右值引用时,需要特别小心不要使用已经被移动的对象,避免悬空引用和未定义行为。
总结一下,使用 std::move可以带来以下好处:
- 避免不必要的深度拷贝,提高程序性能。
- 在传递大型对象或者管理资源的类时,避免额外的内存分配和数据复制。
- 支持使用移动构造函数和移动赋值运算符,以提高程序的性能和资源利用率。
案例分析:
#include <bits/stdc++.h>
using namespace std;
template<typename T>
void fun(T&& t)
{
cout << t << endl;
}
int getInt()
{
return 5;
}
int main() {
int a = 10;
int& b = a; //b是左值引用
int& c = 10; //错误,c是左值不能使用右值初始化
int&& d = 10; //正确,右值引用用右值初始化
int&& e = a; //错误,e是右值引用不能使用左值初始化
const int& f = a; //正确,左值常引用相当于是万能型,可以用左值或者右值初始化
const int& g = 10;//正确,左值常引用相当于是万能型,可以用左值或者右值初始化
const int&& h = 10; //正确,右值常引用
const int& aa = h;//正确
int& i = getInt(); //错误,i是左值引用不能使用临时变量(右值)初始化
int&& j = getInt(); //正确,函数返回值是右值
fun(10); //此时fun函数的参数t是右值
fun(a); //此时fun函数的参数t是左值
return 0;
}