c++ stl find和find_if, 迭代器

c++之使用emplace_back()取代push_back()


C++的emplace_back函数介绍_c++ emplace_back-CSDN博客


 

https://www.cnblogs.com/ChrisCoder/p/9919646.html

C++ STL迭代器原理和实现_05jin的博客-CSDN博客_stl迭代器实现

C++STL迭代器实现原理之三:迭代器的实现与使用_编程砖家的博客-CSDN博客_stl迭代器实现

  • push_back()函数向容器中加入一个临时对象(右值元素)时, 首先会调用构造函数生成这个对象,然后条用拷贝构造函数将这个对象放入容器中, 最后释放临时对象。但是emplace_back()函数向容器中中加入临时对象, 临时对象原地构造,没有赋值或移动的操作。
#include <vector>  
#include <string>  
#include <iostream>  

struct President  
{  
    std::string name;  
    std::string country;  
    int year;  

    President(std::string p_name, std::string p_country, int p_year)  
        : name(std::move(p_name)), country(std::move(p_country)), year(p_year)  
    {  
        std::cout << "I am being constructed.\n";  
    }
    President(const President& other)
        : name(std::move(other.name)), country(std::move(other.country)), year(other.year)
    {
        std::cout << "I am being copy constructed.\n";
    }
    President(President&& other)  
        : name(std::move(other.name)), country(std::move(other.country)), year(other.year)  
    {  
        std::cout << "I am being moved.\n";  
    }  
    President& operator=(const President& other);  
};  

int main()  
{  
    std::vector<President> elections;  
    std::cout << "emplace_back:\n";  
    elections.emplace_back("Nelson Mandela", "South Africa", 1994); //没有类的创建  

    std::vector<President> reElections;  
    std::cout << "\npush_back:\n";  
    reElections.push_back(President("Franklin Delano Roosevelt", "the USA", 1936));  

    std::cout << "\nContents:\n";  
    for (President const& president: elections) {  
       std::cout << president.name << " was elected president of "  
            << president.country << " in " << president.year << ".\n";  
    }  
    for (President const& president: reElections) {  
        std::cout << president.name << " was re-elected president of "  
            << president.country << " in " << president.year << ".\n";  
}
  • 据统计,emplace_back()函数要比push_back()函数要快一倍。

(700条消息) C++ std::pair的用法_std pair_吉大秦少游的博客-CSDN博客

C++ vector的reserve和resize详解

C++ vector的reserve和resize详解 - 篮球之神Michael - 博客园

vector 的reserve增加了vector的capacity,但是它的size没有改变!而resize改变了vector的capacity同时也增加了它的size!
原因如下:

 reserve是容器预留空间,但在空间内不真正创建元素对象,所以在没有添加新的对象之前,不能引用容器内的元素。加入新的元素时,要调用push_back()/insert()函数。

      resize是改变容器的大小,且在创建对象,因此,调用这个函数之后,就可以引用容器内的对象了,因此当加入新的元素时,用operator[]操作符,或者用迭代器来引用元素对象。此时再调用push_back()函数,是加在这个新的空间后面的。

 

STL----pair以及tuple_tuple和pair的区别_1.01的博客-CSDN博客

list , vector  find

C++11 find和find_if的用法_zzhongcy的博客-CSDN博客_find_if

       STL的find,find_if函数提供了一种对数组、STL容器进行查找的方法。使用该函数,需 #include <algorithm>
我们查找一个list中的数据,通常用find(),例如:


			vector<string>::iterator iter;
			iter = find(channelInfo->begin(), channelInfo->end(), strategyId);

			auto find = 0;
			if (iter != channelInfo->end())
			{
				//vec中存在"SZ000001"
				find = 1;
			}

我们在CPerson类外部定义这样一个结构体:
typedef struct finder_t
{
    finder_t(int n) : age(n) { } 
    bool operator()(CPerson *p) 
    { 
        return (age == p->age); 
    } 
    int age;
}finder_t;

然后就可以利用find_if函数来查找了:
list<CPerson*> lst;
// 向lst中添加元素,此处省略

list<CPerson*>::iterator it = find_if(lst.begin(), lst.end(), finder_t(50)); // 查找年龄为50的人
if (it != lst.end()) // 找到了
{
    cout << "Found person with age : " << (*it)->age;
}
else // 没找到
{
    // do something
}

STL容器是线程不安全的----以及加锁实现多线程访问安全

STL容器是线程不安全的----以及加锁实现多线程访问安全_guochampion的博客-CSDN博客_stl容器是线程不安全的

一般说来,stl对于多线程的支持仅限于下列两点:(貌似Effective STL中有描述)

1.多个读取者是安全的。即多个线程可以同时读取一个容器中的内容。 即此时多个线程调用 容器的不涉及到写的接口都可以 eg find, begin, end 等.

2.对不同容器的多个写入者是安全的。即多个线程对不同容器的同时写入合法。 但是对于同一容器当有线程写,有线程读时,如何保证正确? 需要程序员自己来控制,比如:线程A读容器某一项时,线程B正在移除该项。这会导致一下无法预知的错误。 通常的解决方式是用开销较小的临界区(CRITICAL_SECTION)来做同步。以下列方式同步基本上可以做到线程安全的容器(就是在有写操作的情况下仍能保证安全)。

  1.每次调用容器的成员函数的期间需要锁定。

  2.每个容器容器返回迭代器的生存期需要锁定。

  3.每个容器在调用算法的执行期需要锁定。

  和小罗的关于task_server的多线程安全的交流: 是这样的, 当你调用map的任何接口时, 比如 end(), begin(), find()等时, 可能会返回一个iterator, 如果有别的线程正在修改这个map, 你的iterator就变得无效了, 再用这个iterator行为就可能出问题. 或者在find()函数内部, 会访问到map内部的红黑树的数据结构, 而这个红黑树是有可能被别的线程调整的(比如别的现在往map中插入一个不存在的记录). 所以, 是危险的.

我们通常通过为容器加锁来保证容器的线程安全性。

为容器加锁:

  • 多个读取者是安全的。多线程可能同时读取一个容器的内容,这将正确地执行。当然,在读取时不能有任何写入者操作这个容器。

  • 对不同容器的多个写入者是安全的。多线程可以同时写不同的容器。

多线程操作C++ STL vector出现概率coredump问题及尽量避免锁的双缓冲队列

多线程操作C++ STL vector出现概率coredump问题及尽量避免锁的双缓冲队列 - 大老虎打老虎 - 博客园

最后,回到我遇到的那个问题,定时更新配置,可以考虑加锁。如果不用锁, 该怎么实现呢? 可以考虑用两个vector, 轮换使用,更新的vector不去读, 当前的读的vector不更新,然后轮换当前vector.  我见过很多地方都是这么用的。

       类似的问题还有很多很多, 坑, 就在那里, 不多不少。 书本Effective STL第12 条如是说:切勿对STL 容器的线程安全性有不切实际的依赖!

双缓冲队列文章,注意双缓冲队列不是完全不加锁 而是尽可能的减少加减锁

C++11 实现生产者消费者双缓冲

C++11 实现生产者消费者双缓冲 - karllen - 博客园

实现一个双缓冲队列 - 重庆肥猫 - 博客园

C++ STL中的 Set的用法

C++ STL中的 Set的用法 - 生活待我如初恋 - 博客园

set   是STL中的集合。

  集合我们都很熟悉,具有排异性,在这里set中也遵循这条规矩。 而且在set中,存在系统自动排序的操作。

C++/C++11中std::set用法汇总_Frank.Ginger的博客-CSDN博客_c++11 set

标准库提供8个关联容器:

(1)、按关键字有序保存元素:map(关联数组:保存关键字----值对);set(关键字即值,即只保存关键字的容器);multimap(关键字可重复出现的map);multiset(关键字可重复出现的set);

(2)、无序集合:unordered_map(用哈希函数组织的map);unordered_set(用哈希函数组织的set);unordered_multimap(哈希组织的map,关键字可以重复出现);unordered_multiset(哈希组织的sest,关键字可以重复出现)。

map是关键字----值对的集合,与之相对,set就是关键字的简单集合。当只是想知道一个值是否存在时,set是最有用的。

在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。Set中元素的值不能直接被改变。set内部采用的是一种非常高效的平衡检索二叉树:红黑树,也称为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树。

下面是从cplusplus和cpp

list函数splice

list::splice()函数详解 - 小 楼 一 夜 听 春 雨 - 博客园

list::splice实现list拼接的功能。将源list的内容部分或全部元素删除,拼插入到目的list。

函数有以下三种声明:

void splice ( iterator position, list<T,Allocator>& x );  // 

void splice ( iterator position, list<T,Allocator>& x, iterator i );

void splice ( iterator position, list<T,Allocator>& x, iterator first, iterator last );

函数说明:在list间移动元素:

将x的元素移动到目的list的指定位置,高效的将他们插入到目的list并从x中删除。

目的list的大小会增加,增加的大小为插入元素的大小。x的大小相应的会减少同样的大小。

前两个函数不会涉及到元素的创建或销毁。第三个函数会。

指向被删除元素的迭代器会失效。

// splicing lists
#include <iostream>
#include <list>

int main ()
{
  std::list<int> mylist1, mylist2;
  std::list<int>::iterator it;

  // set some initial values:
  for (int i=1; i<=4; ++i)
     mylist1.push_back(i);      // mylist1: 1 2 3 4

  for (int i=1; i<=3; ++i)
     mylist2.push_back(i*10);   // mylist2: 10 20 30

  it = mylist1.begin();
  ++it;                         // points to 2

  mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4
                                // mylist2 (empty)
                                // "it" still points to 2 (the 5th element)
                                          
  mylist2.splice (mylist2.begin(),mylist1, it);
                                // mylist1: 1 10 20 30 3 4
                                // mylist2: 2
                                // "it" is now invalid.
  it = mylist1.begin();
  std::advance(it,3);           // "it" points now to 30

  mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end());
                                // mylist1: 30 3 4 1 10 20

  std::cout << "mylist1 contains:";
  for (it=mylist1.begin(); it!=mylist1.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  std::cout << "mylist2 contains:";
  for (it=mylist2.begin(); it!=mylist2.end(); ++it)
    std::cout << ' ' << *it;
  std::cout << '\n';

  return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值