前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【C++11】 C++11中不常用特性

【C++11】 C++11中不常用特性

作者头像
CPP开发前沿
发布2021-11-16 14:19:30
4090
发布2021-11-16 14:19:30
举报
文章被收录于专栏:CPP开发前沿CPP开发前沿

今天主要说的事C++11中的在实际开发中很少用到的特性,这些特性虽然很少用,但是使用之后又让人眼前一亮,心生佩服。比如通过委托构造函数和集成构造函数可以少写很多不必要的函数,使用final和override可以增强代码的可读性且可以避免很多低级错误等等。

1 委托构造函数和集成构造函数

1.1 委托构造函数

委托构造函数云讯在同一个勒种一个构造函数可以调用 另外一个构造函数,代码如下:

代码语言:javascript
复制
class GetNumber{
public:
    GetNumber(int iMax):max(iMax){}
    GetNumber(int iMax,int iMin):GetNumber(iMax)
    {
        min = iMin >0 && iMin<iMax? iMin:1;
    }
    GetNumber(int iMax,int iMin,int iMiddle):GetNumber(iMax,iMin)
    {
        middle = iMiddle > iMin && iMiddle < iMax ? iMiddle:2;
    }
private:
    int max;
    int min;
    int middle;
};

委托构造函数需要注意的是,如果使用了代理构造函数就不能使用类成员函数初始化,而要使用变量赋值的方法。

1.1 继承构造函数

C++11中,允许派生函数使用基类的构造函数,这样可以极大简化构造函数的编写,尤其是在基类成构造函数较多的情况下。使用方法如下:

代码语言:javascript
复制
class Base{
public:
    Base(int iMax):max(iMax){};
    Base(int iMax,int iMin):max(iMax),min(iMin)
    {
        
    }
    Base(int iMax,int iMin,int iMiddle):max(iMax),min(iMin),middle(iMiddle)
    {
       
    }
private:
    int max;
    int min;
    int middle;
};

class Derived:Base{
    using Base::Base;
};
int main ()
{
  Derived d(1);
  return 0;
}

从上面代码中可以看到,在派生类中使用using语句后派生类可以减少很多构造函数的编写。

2 原始的字面量

编码时如果遇到需要传入文件路径时,一般要加上转义符,才能正确表示一个文件路径,C++11后,新增了原始字符串字面量“R”,原始字面量的使用不需要我们对字符串进行特殊处理,输出时就会输出字符串原始的含义。使用方法为:

代码语言:javascript
复制
int main ()
{
 std::string str = R"test(d:\A\B\test.bat)test";
 std::cout<<str;
 return 0;
}

上面的代码如果通过编译器进行输出的话输出内容为:

代码语言:javascript
复制
d:\A\B\test.bat 

使用时需要注意的点是:

  • 原始字符串必须用()括起来
  • 括号前后可以加字符串,但是必须在括号两边保持一致,且不会被输出。

3 final和override

和java语言类似,final标识符表示类不能被继,或者虚函数不能被重写,写法如下:

代码语言:javascript
复制
class A
{
    virtual void Add() final;
};

如果在非虚函数上加final,则编译会报错,如:

代码语言:javascript
复制
class A
{
    void Add() final;//编译报错
};

报错信息如下:

代码语言:javascript
复制
 error: 'void A::Add()' marked final, but is not virtual

同理,如果类被定义成了final:

代码语言:javascript
复制
class A final 
{
    void Add();
};

class B:A
{
};

报错信息如下:

代码语言:javascript
复制
error: cannot derive from 'final' base 'A' in derived type 'B'

override标识符可以提高代码的可读性,避免因为失误导致的本来要重写的虚函数变成重载。使用方法如下:

代码语言:javascript
复制
class A
{
    virtual void Add();
};

class B:A
{
    void Add() override
    {
    }
};

4 C++ 11 中新增的便利算法

C++ 11中新增了一些便利的算法,使用后,代码将会变得更加简洁、方便。

4.1 all_of,any_of,none_of

三个算法的原型为:

代码语言:javascript
复制
template <class InputIterator, class UnaryPredicate>
  bool all_of (InputIterator first, InputIterator last, UnaryPredicate pred);
template <class InputIterator, class UnaryPredicate>
  bool any_of (InputIterator first, InputIterator last, UnaryPredicate pred);
template <class InputIterator, class UnaryPredicate>
  bool none_of (InputIterator first, InputIterator last, UnaryPredicate pred);

这三个算法均对一个检查区间进行查找,查找条件满足一个一元判断式。如果有一个元素满足条件,则返回true,否则返回false。代码如下:

代码语言:javascript
复制
int main () {
  std::array<int,8> foo = {1,2,4,8,16,32,64,128};

  if ( std::none_of(foo.begin(), foo.end(), [](int i){return i<0;}) )
    std::cout << "所有的数都不小于0.\n";

 if ( std::all_of(foo.begin(), foo.end(), [](int i){return i%2 == 0;}) )
    std::cout << "所有的数都是偶数.\n";
    
 if ( std::any_of(foo.begin(), foo.end(), [](int i){return i%2 == 1;}) )
    std::cout << "至少有一个数是奇数.\n";

  return 0;
}

代码运行结果为:

代码语言:javascript
复制
所有的数都不小于0.
至少有一个数是奇数.

4.2 find_if_not 、find_if算法

该算法的功能和find_if相反,虽然通过彼此都可以相互实现,但是为了编码时不用再写否定判断式提升代码可读性,还是新增了单独的算法进行实现,代码使用方法如下:

代码语言:javascript
复制
int main () {
  std::array<int,5> foo = {1,2,3,4,5};

  std::array<int,5>::iterator it =
    std::find_if_not (foo.begin(), foo.end(), [](int i){return i%2;} );
  std::cout << "The first even value is " << *it << '\n';
  
    std::array<int,5>::iterator it1 =
    std::find_if (foo.begin(), foo.end(), [](int i){return i%2==0;} );
  std::cout << "The first even value is " << *it1 << '\n';

  return 0;
}

如上代码所示,输出结果是一样,都是:The first even value is 2

4.3 copy_if 算法

通copy算法一样,都是拷贝一段区间内的值,但是copy_if增加了一个条件,只有满足条件的才会进行拷贝,copy_if原型如下:

代码语言:javascript
复制
template <class InputIterator, class OutputIterator, class UnaryPredicate>
  OutputIterator copy_if (InputIterator first, InputIterator last,
                          OutputIterator result, UnaryPredicate pred)
{
  while (first!=last) {
    if (pred(*first)) {
      *result = *first;
      ++result;
    }
    ++first;
  }
  return result;
}

使用方法如下:

代码语言:javascript
复制
int main () {
  std::vector<int> foo = {1,2,3,-1,-2};
  std::vector<int> bar (foo.size());

  auto it = std::copy_if (foo.begin(), foo.end(), bar.begin(), [](int i){return (i<0);} );
  bar.resize(std::distance(bar.begin(),it));

  std::cout << "bar contains:";
  for (int& x: bar) std::cout << ' ' << x;
  std::cout << '\n';

  return 0;
}

上面代码输出结果为:bar contains: -1 -2。

PS:std::distance是计算两个迭代器区间范围内的元素数。

4.4 iota 算法

算法库中该算法可以用来在固定的数组上生成有序数列。使用方法如下:

代码语言:javascript
复制
int main () {
  int numbers[10];
  std::iota (numbers,numbers+10,100);
  std::cout << "numbers:";
  for (int& i:numbers) std::cout << ' ' << i;
  std::cout << '\n';
  return 0;
}

上面代码运行结果为:numbers: 100 101 102 103 104 105 106 107 108 109

由运行结果可知,算法给固定长度数组进行了初始化,初始化的值为第三个参数自增。

4.5 minmax_elemen

该算法可以同时获得数组或者容器中的最大值和最小值,使用方法如下:

代码语言:javascript
复制
int main () {
  std::vector<int> foo {3,7,2,9,5,8,6};
  auto result = std::minmax_element (foo.begin(),foo.end());
  std::cout << "min is " << *result.first;
  std::cout << ", at position " << (result.first-foo.begin()) << '\n';
  std::cout << "max is " << *result.second;
  std::cout << ", at position " << (result.second-foo.begin()) << '\n';
  return 0;
}

上面代码运行结果为:

代码语言:javascript
复制
min is 2, at position 2
max is 9, at position 3

4.6 is_sorted 和is_sorted_until算法

  • is_sorted :判断序列是否是有序序列
  • is_sorted_until:返回序列中已排好序的部分

使用方法如下:

代码语言:javascript
复制
int main () {
 std::array<int,4> foo {2,4,1,3};
 auto pos = std::is_sorted_until(foo.begin(),foo.end());
 for(auto it =foo.begin();it != pos;it++)
 {
     std::cout<<*it<<", ";
 }
 std::cout<<std::endl;
 
 bool isSorted = std::is_sorted(foo.begin(),foo.end());
 if(!isSorted)
 {
     std::cout<<"数组为非完全排序"<<std::endl;
 }
  return 0;
}

代码运行结果如下:

代码语言:javascript
复制
2, 4, 
数组为非完全排序
本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-10-08,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 CPP开发前沿 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
容器服务
腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档