首页 > 编程语言 >C++ primer plus 第16章string 类和标准模板库, 函数符概念

C++ primer plus 第16章string 类和标准模板库, 函数符概念

时间:2024-07-26 11:57:53浏览次数:18  
标签:cutoff const 函数 16 C++ 参数 vals 100 string

C++ primer plus 第16章string 类和标准模板库, 函数符概念

C++ primer plus 第16章string 类和标准模板库, 函数符概念

文章目录


16.5.1 函数符概念

正如 STL定义了容器和迭代器的概念一样,它也定义了函数符概念。

  • 生成器(gencrator)是不用参数就可以调用的函数符。
  • 一元函数(unaryfunction)是用一个参数可以调用的函数符
  • 二元函数(binary function)是用两个参数可以调用的函数符。

例如,提供给foreach()的函数符应当是一元函数,因为它每次用于一个容器元素。当然,这些概念都有相应的改进版:

  • 返回 bool值的一元函数是谓词(predicate);
  • 返回 bool值的二元函数是二元谓词(binarypredicate)。

些 STL函数需要谓词参数或二元谓词参数。例如,程序清单16.9使用了sor()的这样一个版本,即将二元谓词作为其第3个参数:

bool WorseThan(const Review&rl,const Review&r2);
...
sort(books.begin(),books.end(),worseThan);

list 模板有一个将谓词作为参数的removei)成员,该函数将谓词应用于区间中的每个元素,如果谓词返回 true,则删除这些元素。例如,下面的代码删除链表three 中所有大于100的元素:

bool tooBig(int n){return n>100}:
list<int> scores;
 ...
scores.remove_if(tooBig);

最后这个例子演示了类函数符适用的地方。假设要删除另一个链表中所有大于200的值。如果能将取舍值作为第二个参数传递给tooBig(),则可以使用不同的值调用该函数,但谓词只能有一个参数。然而,如果设计一个 TooBig 类,则可以使用类成员而不是函数参数来传递额

template<class T>
class TooBig
private :
T cutoff;
public :
TooBig(const T&t):cutoff(t){}
bool operator()(constT&v){return v>cutoff};
}:

这里,一个值(V)作为函数参数传递,而第二个参数(cutof)是由类构造函数设置的。有了该定义后,就可以将不同的TooBig对象初始化为不同的取舍值,供调用removei()时使用。程序清单 16.15 演示了这种技术。

程序清单16.15 functor.cpp

// functor.cpp -- using a functor
#include <iostream>
#include <list>
#include <iterator>
#include <algorithm>

template<class T>  // functor class defines operator()()
class TooBig
{
private:
    T cutoff;
public:
    TooBig(const T & t) : cutoff(t) {}
    bool operator()(const T & v) { return v > cutoff; }
};

void outint(int n) {std::cout << n << " ";}

int main()
{
    using std::list;
    using std::cout;
    using std::endl;
	using std::for_each;
	using std::remove_if;

    TooBig<int> f100(100); // limit = 100
    int vals[10] = {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};
    list<int> yadayada(vals, vals + 10); // range constructor
    list<int> etcetera(vals, vals + 10);
 
 // C++0x can use the following instead
//  list<int> yadayada = {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};
//  list<int> etcetera {50, 100, 90, 180, 60, 210, 415, 88, 188, 201};

    cout << "Original lists:\n";
    for_each(yadayada.begin(), yadayada.end(), outint);
    cout << endl;
    for_each(etcetera.begin(), etcetera.end(), outint);
    cout << endl;
    yadayada.remove_if(f100);               // use a named function object
    etcetera.remove_if(TooBig<int>(200));   // construct a function object
    cout <<"Trimmed lists:\n";
    for_each(yadayada.begin(), yadayada.end(), outint);
    cout << endl;
    for_each(etcetera.begin(), etcetera.end(), outint);
    cout << endl;
    // std::cin.get();
    return 0;
}

-个函数符(f100)是一个声明的对象,而另一个函数符(TooBig(200))是一个匿名对象,它是由构造函数调用创建的。下面是程序清单16.15中程序的输出:

在这里插入图片描述
假设已经有了一个接受两个参数的模板函数:

template <class T>
bool tooBig(const T&val,const T& lim)
{
return val >lim;
}

则可以使用类将它转换为单个参数的函数对象:

template<class T>
class TooBig2
{
private:
	T cutoff;
public:
	TooBig2(const T&t):cutoff(t){}
 
	bool operator()(const T&v){return tooBig<T>(v,cutoff);}
};

即可以这样做:

TooBig2<int>tB100(100);
int x;
cin >> X;
if(tB100(x))	//same as if(tooBig(x,100))
...

因此,调用 tB100(x)相当于调用 tooBig(x,100),但两个参数的函数被转换为单参数的函数对象,其中第二个参数被用于构建函数对象。简而言之,类函数符TooBig2是一个函数适配器,使函数能够满足不同的接口。
在该程序清单中,可使用C++11的初始化列表功能来简化初始化。为此,可将如下代码:

int vals[10]={50,100,90,180,60,210,415,88,188,201};
list<int>yadayada(vals,vals +10);//range constructor
list<int>etcetera(vals,vals + 10);

替换为下述代码:

list<int>yadayada=(50,100,90,180,60,210,415,88,188,201}
list<int>etcetera(50,100,90,180,60,210,415,88,188,201};

标签:cutoff,const,函数,16,C++,参数,vals,100,string
From: https://blog.csdn.net/zhyjhacker/article/details/140711839

相关文章

  • C++ primer plus 第16章string 类和标准模板库, 函数对象
    C++primerplus第16章string类和标准模板库,函数对象C++primerplus第16章string类和标准模板库,函数对象文章目录C++primerplus第16章string类和标准模板库,函数对象16.5函数对象16.5函数对象很多STL算法都使用函数对象–也叫函数符(fiunctor)。......
  • 当你第一次用C++string的assign会遇到这种情况
    当你第一次用string的assign时,会发现有一点小区别,见以下代码:stringstr1;str1.assign("helloC++");cout<<str1<<endl;stringstr2;str2.assign(str1,5);cout<<str1<<endl;stringstr3;str3.assign("helloC++",5);cout<<......
  • 使用pybind11封装c++的dll,供python调用
    用pip安装好pybind11 文件清单,都写在一个目录里//文件名:add.cppextern"C"doubleadd(doublein1,doublein2){returnin1+in2;}//文件名:sub.cppextern"C"doublesub(doublein1,doublein2){returnin1-in2;}//文件名:mul.cppextern"......
  • P9304 「DTOI-5」3-1题解,c++树的遍历例题
    题意给定以n(1≤n≤1......
  • C/C++默认生成的几个函数s
    一、关键词类/结构体默认生成。拷贝/移动+构造/赋值=组合不同方式有4种,除默认、析构,共计6种。在使用时:拷贝/移动+赋值的,都是定义和赋值分开;拷贝/移动+构造的,都是定义和赋值一起。二:知识点默认构造函数Student():age(0){};拷贝构造函数Student(constStudent&i......
  • C++ typeid 关键字的注意事项
    typeid 是C++的一个关键字,用于动态类型获取。typeid 运算符与RTTI(运行时类型信息)密切相关,它返回一个指向 std::type_info 对象的引用,该对象表示了表达式的类型。使用 typeid 时,需要注意以下几个方面:需要#include <typeinfo>头文件:要使用 typeid,应在代码中包含 <t......
  • C++ 虚基类注意事项
    C++中的虚基类(VirtualBaseClass)是一个重要的概念,主要用于解决多重继承中的菱形继承问题,即当一个派生类通过多条路径继承同一个基类时,基类在派生类中会有多个副本,导致资源浪费和不必要的复杂性。以下是C++虚基类的一些详细注意事项:1.虚基类的定义与声明定义方式:虚基类并不......
  • PYTHON 代码执行错误 - 冻结 importlib._bootstrap>(1165)_find_and_load()?
    在MACOS10.15(CATALINA)上执行此PYTHON代码时出现以下错误。我正在使用IDLEShell编写PYTHON3.11。Python3.11.4(v3.11.4:d2340ef257,Jun 62023,19:15:51)[Clang13.0.0(clang-1300.0.29.30)]ondarwinType"help","copyright","credits"o......
  • C++中的智能指针与裸指针有什么区别?
    在C++中,智能指针是一种特殊类型的指针对象,它能自动管理内存的分配和释放。智能指针与裸指针(即传统的指针)之间有以下区别:自动资源管理:智能指针通过使用引用计数或其他机制来自动管理内存资源的分配和释放。这意味着当不再需要指针指向的对象时,智能指针会自动释放内存,避免......
  • C++中的虚函数与多态机制如何工作?
    在C++中,虚函数和多态机制是实现面向对象编程的重要概念。虚函数是在基类中声明的函数,可以在派生类中进行重写。当基类的指针或引用指向派生类的对象时,通过调用虚函数可以实现动态绑定,即在运行时确定要调用的函数。多态是指通过基类的指针或引用调用虚函数时,会根据对象的实......