4.1 函数对象包装器
C++11 std::function 是一种通用、多态的函数封装,它的实例可以对任何可以调用的目标实体进行存储、复制和调用操作,它也是对 C++ 中现有的可调用实体的一种类型安全的包裹(相对来说,函数指针的调⽤不是类型安全的),换句话说,就是==函数的容器==。当我们有了函数的容器之后便能够更加方便的将函数、函数指针作为对象进行处理。
==example_9 code==
#include <iostream>
#include <functional> //必须头文件
int foo(int a)
{
return a;
}
int main()
{
std::function<int(int)> func = foo; //包装了一个返回值为int,参数为int的函数
int important = 10;
std::function<int(int)> func2 = [&](int value)->int{
return 1 + value + important;
};
std::cout<<func(10)<<std::endl;
std::cout<<func2(10)<<std::endl;
}
4.2 std::array
std::array 保存在栈内存中,相比堆内存中的 std::vector,我们就能够灵活的访问这里面的元素,从而获得更好的性能。使用std::array能够让代码变得更加现代,且封装了一些操作函数,同时还能够友好的使用标准库中的容器算法等等,比如 std::sort。
语法格式:
std :: array <int , 4> arr = {1 ,2 ,3 ,4}; //固定大小,不能隐式转为指针
// C 风 格 接 口 传 参
// foo (arr , arr . size ()); // 非 法 , 无 法 隐 式 转 换
foo (& arr [0] , arr. size ()); //显示转换为指针
foo( arr. data () , arr. size ());//显示转换为指针
// 使 用 ‘std :: sort ‘
std :: sort ( arr. begin () , arr. end ());
4.3 std::tuple
关于元组的使用有三个核心的函数:
- std::make_tuple: 构造元组
- std::get: 获得元组某个位置的值
- std::tie: 元组拆包
例子==example_11 code==:
#include <iostream>
#include <tuple>
#include <string>
int main()
{
auto t = std::make_tuple(3.8, "A", "Barret Ren");
//get获取元素
std::cout<<std::get<0>(t)<<std::endl;
std::cout<<std::get<1>(t)<<std::endl;
std::cout<<std::get<2>(t)<<std::endl;
//tie进行拆包
double a;
std::string b;
std::string c;
std::tie(a, 大专栏 C++17特性:标准库ass="n">b, c)=t;
std::cout<<c<<std::endl;
}
std::tuple 虽然有效,但是标准库提供的功能有限,没办法满足运行期索引和迭代的需求,好在我们还有其他的方法可以实现。需要==boost库==的支持。
4.4 std::size()
C++17开始,可以使用std::size()获取传统C数组的个数。 int myArray[]={1,2,3,4};
std::cout<<std::size(myArray)<<std::endl;
4.5 string.data()
C++14开始,string类的新函数data()可以和c_str()一样返回C风格字符数组(const char);C++17开始,对于non-const string变量,返回char数组,非const char*:
std::string a="hello";
char b[10];
strcpy(b, a.data());
4.6 string与int/double等之间的转换
int/double等转换为string,例如123—>”123”:
string转换为int/double等类型,代替atoi,idx表示第一个不能转换为数字的字符位置:
4.7 std::string_view
C++17引入了新的类std::string_view,用于代替const string&或const char。 构造string_view的时候用char和长度来构造,这个长度可以自由确定,它表示string_view希望引用的字符串的长度。因为它只是引用其他字符串,所以它==不会分配内存==,不会像string那样容易产生临时变量,==节省内存和运行时间==。
例子==example_18 code==:
#include <iostream>
#include <string>
#include <string_view>
#include <ctime>
using namespace std::string_view_literals; //用于使用sv标记
int main(int argc, char const *argv[])
{
auto view="it is a test"sv;//sv表示字符串是string_view类型
std::string str="it is a test";
std::clock_t time1=clock();
for(int i=0; i<1000000; i++)
{
auto s1=view.substr(3);
}
std::clock_t time2=clock();
std::cout<<static_cast<double>(time2-time1)/CLOCKS_PER_SEC*1000<<std::endl;
time1=clock();
for(int i=0; i<1000000; i++)
{
auto s2=str.substr(3);
}
time2=clock();
std::cout<<static_cast<double>(time2-time1)/CLOCKS_PER_SEC*1000<<std::endl;
return 0;
}
//输出
//16
//115
stringh_view提供和string类似的方法,但是并不能相互转化。可以通过data()获取字符串再与string类型计算。
string str = "Hello";
string_view sv = " world";
auto result = str + sv; //错误
auto result = str + sv.data(); //正确