NDK-029: C++10:STL函数对象和谓词

2025-01-14  本文已影响0人  xqiiitan

29.C++进阶 - STL函数对象和谓词

C++文档 http://en.cppreference.com/w/c

1.map容器

map会对key 进行排序
添加数据方式的区别,前面三种,key重复时,数据插入 不生效(后面的插入不会生效)。
第四种插入方式,会覆盖写入。
如果要判断是否添加成功,如何处理?参考Day28内容。insert有返回值pair。

map会根据key,进行数据排序,里面使用二叉树算法。

#include <map>
#include <iostream>
using namespace std;
void main() {
    map<int, string> map1;
    // 数据添加的几种方式
    map1.insert(pair<int, string>(01, "01"));
    map1.insert(make_pair(02, "02"));
    map1.insert(map<int, string>::value_type(03,"03"));
    map1[04]= "04"; // 常用的添加方式: map1[key]=value
    
    // 遍历-迭代器
    for(map<int,string>::iterator it=map1.begin(); it!=map1.end(); it++){
        cout << it->first <<"~" << (it->second).c_str() << endl;
    }   
    // 删除,查找
    map<int,string>::iterator find_it = map1.find(100);
    if(find_it != map1.end()){
        // 找到
        cout << find_it->first << endl;
    } else{
        // 找不到  
    }
}

2.multimap容器介绍

允许key键重复的容器, 根据key就行排序。

void main() {
    multimap<int, string> map1;
    // 1班:11,12,13, 2班:21,22,23 三班:31,32,33
    map1.insert(pair<int,string>(1,"11"));
    map1.insert(pair<int,string>(1,"12"));
    map1.insert(pair<int,string>(1,"13"));
    
    map1.insert(pair<int,string>(2,"21"));
    map1.insert(pair<int,string>(2,"22"));
    map1.insert(pair<int,string>(2,"23"));
    
    map1.insert(pair<int,string>(3,"31"));
    map1.insert(pair<int,string>(3,"32"));
    map1.insert(pair<int,string>(3,"33"));
    
    for(map<int,string>::iterator it=map1.begin(); it!=map1.end(); it++){
        cout << it->first <<"~" << (it->second).c_str() << endl;
    }
    cout << "----------------" << endl;
    // 分组查询,每组多个数据
    multimap<int,string>::iterator  find_it = map1.find(1);
    while(find_it != map1.end()) {
        cout << it->first << "~" << (it->second).c_str() << endl;
        find_it++;
        
        if(find_it==map1.end() || find_it->first !=1) { // 不是目标分组
            break;
        }
    }
}

3.容器对象- 拷贝构造函数

java中会把对象添加到集合中;
C++中会调用对象的 拷贝构造函数,存进去的是另一个对象。

注意:如果想要存同一个对象,在任何地方改变,集合的数据也相应的发生变化,
就可以用指针,存储的时候存 指针。

class Person {
public: string name;
    char *test;
    
public:
    Person(){} // 默认构造函数
    Person(string name){this->name = name;}
    Person(const Person& person) {
        cout << "拷贝构造函数" << endl;
        this->name = person.name;
        test = (char*) malloc(10);
    }
    ~Person() {
        // 释放malloc申请的内存
        free(test);
        cout << "析构函数"<< endl;
    }
public:
    void setName(string name) {this->name =name;}
}

void main() {

// 第一个错误:没有默认的构造函数
// 第二个错误:西沟函数也可能回调多次,如果在析构函数中释放了内存,需要在拷贝构造函数中就行深拷贝。
// 避免被反复析构同一片内存。 导致宕机。
    vector<Person> vector1;
    Person person("Darren");
    vector1.push_back(person); // 调用对象的拷贝构造函数,传入的不是person对象。
        
    person.setName("Jack");
    Person person1 = vector.front(); // 调用拷贝构造函数
    cout << person1.name.c_str() << endl;
}

析构函数也可能回调多次,如果在析构函数中释放了内存,需要在拷贝构造函数中就行深拷贝。
不能直接地址赋值。

4.函数对象(仿函数) 一元谓词/二元谓词

谓词:遵循一定规律,做回调用的,
一元谓词:一个参数的。
二元谓词:两个参数的。

class Compare {
public:
    void operator()(){
        cout << "仿函数" << endl;
    }
}

void compare1() {
    cout << "普通函数" << endl;
}
void main() {
    Compare compare;
    compare(); // 跟函数类似,所以叫仿函数。
    compare1();
}

// 谓词

#include <iostream>
#include <set>
#include <algorithm> // 预定义函数,已实现好的算法 for_each
using namespace std;

// 一元谓词,回调函数
void print(int number) {
    cout << number << endl;
}
// 仿函数:一元谓词函数
class PrintObj {
public:
    int count=0;
public:
    void operator()(int number){
        cout << number << endl;
        count++;
    }
}
// 回调函数与仿函数的区别。
仿函数,可以添加count,记录一些东西。

void main(){
    set<int > set1; // set<int, PrintObj> set1; 这边可以不要括号。
    set1.insert(1);
    set1.insert(2);
    set1.insert(3);
    set1.insert(4);
    // 一元谓词。
    // for_each(set1.begin(), set1.end(), print);    
    // for_each(str1.begin(), str1.end(), PrintObj()); // 回调函数
    
    // 仿函数如果要保存记录状态,要确保对象一致。可以用返回值。
    PrintObj printObj;
    printObj = for_each(str1.begin(), str1.end(), printObj);
    cout << "count个数:"<< printObj.count << endl;
}

二元谓词

// 仿函数(它不是函数,是一个对象,只不过有点像函数): 二元谓词
class CompareObj{
public:
    bool operator()(cosnt string str1,const string str2){//2个参数。
        return str1 > str2;
    }
}

void main(){
    // 传入二元谓词的仿函数
    set<string, CompareObj> set1; 
    set1.insert("aaa");
    set1.insert("aAa");
    set1.insert("CCC");
    set1.insert("ddd");
    // 遍历输出
    for(set<string>::iterator it=str1.begin(); it!=str1.end(); it++){
        cout<< (*it).c_str() << endl;
    }
    
    // 是否包含aaa,可以遍历比较,
/*  vector<string>::iterator find_it =find_if(vector1.begin(),vector1.end(), CompareObj());
    if(find_it !=vector1.end()) {
        // 找到了
    } else { 
        // 没找到
    }*/
}
上一篇 下一篇

猜你喜欢

热点阅读