STL的一些技巧函数使用

1.emplace() 函数和 emplace_back() 函数

C++11的STL中新增加了emplace() 函数和 emplace_back() 函数,用来实现insert() 函数和 push_back() 函数的功能。

如果容器中的元素是对象:

emplace()  函数的功能是可以直接将参数传给对象的构造函数,在容器中构造出一个对象,从而实现 0 拷贝。(底层机制是调用placement new即布局new运算符来实现的)。

假设类MyClass 有构造函数 MyClass(T1 val1,T2 val2);

那么container.emplace(container.end() ,val1, val2) 可以直接在容器的末尾构造出一个对象,如果用container.insert(container.end() ,MyClass(val1,val2)) 会先构造一个对象,然后拷贝到容器的末尾。

同样的,emplace_back() 和 push_back() 的差别类似。

如果是一个已有的对象 MyClass obj;container.emplace(..., obj)  和  container.emplace_back(obj)的效率差不多。

2.stable_sort()方法 与 sort()方法;partition()方法和 stable_partition()方法

#include <iostream>
 #include <vector>
 #include <algorithm>
 
 using namespace std;
 
 bool IsOdd(int i)
 {
     return (i%2 == 1);
 }
 
 int main()
 {
     vector<int> v;
     for(int i = 0; i < 10; i++)
         v.push_back(i);
 
     cout<<"The original elements in the vector are: "<<endl;
     vector<int>::iterator it, bound;
 
     for(it = v.begin(); it != v.end(); it++)
         cout<<*it<<" ";
     cout<<endl;
 
     cout<<"First use the function partition() to separate all elements into 2 groups without ordering: "<<endl;
     //use partition to separate the vector into 2 parts...
     bound = partition(v.begin(), v.end(), IsOdd);
 
     cout << "All odd elements in the vector are:" <<endl;
     for(it = v.begin(); it != bound; it++)
         cout<<*it<<" ";
     cout<<endl;
 
     cout<< "All even elements in the vector are:" <<endl;
     for(it = bound; it != v.end(); it++)
         cout<<*it<<" ";
     cout<<endl;
 
     v.clear();
     for(int i = 0; i < 10; i++)
     v.push_back(i);
 
     cout<<"Secondly use the function stable_partition() to separate all elements into 2 groups with ordering: "<<endl;
     //use stable_partition to separate the vector into 2 parts...
     bound = stable_partition(v.begin(), v.end(), IsOdd);
     
         cout << "All odd elements in the vector are:" <<endl;
     for(it = v.begin(); it != bound; it++)
         cout<<*it<<" ";
     cout<<endl;
 
     cout<< "All even elements in the vector are:" <<endl;
     for(it = bound; it != v.end(); it++)
         cout<<*it<<" ";
     cout<<endl;
     
     return 0;
 }
    The original elements in the vector are:  
     0 1 2 3 4 5 6 7 8 9  
     First use the function partition() to separate all elements into 2 groups without ordering:  
     All odd elements in the vector are:  
     9 1 7 3 5  
     All even elements in the vector are:  
     4 6 2 8 0  
     Secondly use the function stable_partition() to separate all elements into 2 groups with ordering:  
     All odd elements in the vector are:  
     1 3 5 7 9  
     All even elements in the vector are:  
     0 2 4 6 8  

 3. unique()&& unique_copy函数

类属性算法unique的作用是从输入序列中“删除”所有相邻的重复元素

该算法删除相邻的重复元素,然后重新排列输入范围内的元素,并且返回一个迭代器(容器的长度没变,只是元素顺序改变了),表示无重复的值范围得结束。

 1 // sort words alphabetically so we can find the duplicates 
 2 sort(words.begin(), words.end()); 
 3      /* eliminate duplicate words: 
 4       * unique reorders words so that each word appears once in the 
 5       *    front portion of words and returns an iterator one past the 
 6 unique range; 
 7       * erase uses a vector operation to remove the nonunique elements 
 8       */ 
 9  vector<string>::iterator end_unique =  unique(words.begin(), words.end()); 
10  words.erase(end_unique, words.end());
  • 在STL中unique函数是一个去重函数, unique的功能是去除相邻的重复元素(只保留一个),其实它并不真正把重复的元素删除,是把重复的元素移到后面去了,然后依然保存到了原数组中,然后 返回去重后最后一个元素的地址,因为unique去除的是相邻的重复元素,所以一般用之前都会要排一下序。
  • 算法标准库定义了一个名为unique_copy的函数,其操作类似于unique。唯一的区别在于:前者接受第三个迭代器实参,用于指定复制不重复元素的目标序列。unique_copy根据字面意思就是去除重复元素再执行copy运算。
《Effective STL》里这些话可能有用处:
    ● 如果你需要在vector、string、deque或数组上进行完全排序,你可以使用sort或stable_sort。
   ● 如果你有一个vector、string、deque或数组,你只需要排序前n个元素,应该用partial_sort
   ● 如果你有一个vector、string、deque或数组,你需要鉴别出第n个元素或你需要鉴别出最前的n个元素,而不用知道它们的顺序,nth_element是你应该注意和调用的。
   ● 如果你需要把标准序列容器的元素或数组分隔为满足和不满足某个标准,你大概就要找partition或stable_partition。
   ● 如果你的数据是在list中,你可以直接使用partition和stable_partition,你可以使用list的sort来代替sort和stable_sort。
如果你需要partial_sort或nth_element提供的效果,你就必须间接完成这个任务,但正如我在上面勾画的,会有很多选择。

4.STL remove和erase
移除容器里面的元素不应该使用remove算法,而是容器自己的方法erase()。

erase使用:

#include <iostream>
#include <vector>

using namespace std;

int main()
{
    vector<int> arr;
    arr.push_back(6);
    arr.push_back(7);
    arr.push_back(8);
    arr.push_back(9);
    for(vector<int>::iterator it=arr.begin(); it!=arr.end(); )
    {
        if(* it == 8)
        {
            it = arr.erase(it);
        }
        else
        {
            ++it;
        }
    }

  //注意上面不能写成
    /*
        for(vector<int>::iterator it=arr.begin(); it!=arr.end(); it ++)
        {
            if(* it == 8)
            {
                arr.erase(it);     //在erase后,it失效,并不是指向vector的下一个元素,it成了一个“野指针”。
            }
        }
    */
}

  • 条款32:如果你真的想删除东西的话就在类似remove的算法后接上erase


把remove的返回值作为erase区间形式第一个实参传递很常见,这是个惯用法。事实上,remove和erase是亲密联盟,这两个整合到list成员函数remove中。这是STL中唯一名叫remove又能从容器中除去元素的函数:


list<int> li;            // 建立一个list
                // 放一些值进去
li.remove(99);            // 除去所有等于99的元素:
                // 真的删除元素,
                // 所以它的大小可能改变了

原文地址:https://www.cnblogs.com/ranjiewen/p/8260275.html