C++ STL Unique 底层实现原理

Posted 攻城狮小Liu说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C++ STL Unique 底层实现原理相关的知识,希望对你有一定的参考价值。

事实上在搜STL Unique的时候发现网上绝大部分都是错的,包括unique元素提到前面或者非unique元素提到后面。

Unique前后里面的元素是不一样的!!!

Unique前后里面的元素是不一样的!!!

Unique前后里面的元素是不一样的!!!

我们来看代码

#include <bits/stdc++.h>
using namespace std;

class Solution

public:
    int removeDuplicates(vector<int> &nums)
    
        sort(nums.begin(), nums.end());
        for (int i = 0; i < nums.size(); i++)
        
            cout << "#" << nums[i] << endl;
        
        auto last = unique(nums.begin(), nums.end());
        for (int i = 0; i < nums.size(); i++)
        
            cout << "@" << nums[i] << endl;
        
        nums.erase(last, nums.end());
        return nums.size();
    
;

int main()

    vector<int> nums;
    nums.push_back(1);
    nums.push_back(1);
    nums.push_back(2);
    nums.push_back(2);
    nums.push_back(3);
    nums.push_back(5);
    nums.push_back(5);
    Solution s;

    cout << s.removeDuplicates(nums);

输出结果:

#1
#1
#2
#2
#3
#5
#5
@1
@2
@3
@5
@3
@5
@5
4

划重点,最后三个元素,3,5,5

 

再看一个新的:

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
int main()

    int myints[] = 1, 2, 3, 1, 1;
    int len = sizeof(myints) / sizeof(int);
    vector<int> vec(myints, myints + len);
    sort(vec.begin(), vec.end());
    for (int x : vec)
        cout << x << ",";
    cout<<endl;
	unique(vec.begin(), vec.end()), vec.end();
    for (int x : vec)
        cout << x << ",";
    return 0;

  

结果:

 

 

 

得出结论:

事实上是把unique的元素覆盖掉前n个,后面的原来是什么就还是什么

 

看源码:STL Unqiue

这段代码是STL中unique函数的实现代码,其作用是去除一个序列中的连续重复元素,保留第一个出现的元素。代码中包含了一些概念检查的语句。

首先,函数模板unique的定义使用了typename关键字,表示__first和__last是一种类型,而这个类型要满足_Mutable_ForwardIteratorConcept的要求,也就是满足前向迭代器的要求。此外,还要求这个类型的value_type满足_EqualityComparableConcept的要求,即可比较相等。

在函数实现的开头,我们可以看到几个概念检查的语句。其中__glibcxx_function_requires和__glibcxx_requires_valid_range是一些特殊的宏,它们的作用是对参数类型进行概念检查。如果参数类型不满足概念要求,编译器就会报错,从而避免在编译时出现一些潜在的问题。这些概念要求可以在头文件中定义,如上文所示。

最后,代码调用了STL中的__unique函数,该函数是unique函数真正的实现。该函数接受三个参数:序列的起始和结束迭代器,以及一个比较相等的函数对象。该函数对象的作用是用于判断两个元素是否相等。最后,函数返回去重后的序列的尾后迭代器。

 

 再往下:

  1. 首先调用STL中的__adjacent_find函数,查找序列中第一个相邻的重复元素,将__first指向该元素的第一个出现位置。
  2. 如果序列中没有重复元素,直接返回__last。
  3. 否则,从__first+1开始,遍历序列中的所有元素,依次判断当前元素是否与前一个元素相等,如果相等,则跳过该元素,否则将该元素复制到结果序列中,并将结果序列的指针__dest向前移动一位。
  4. 最后返回去重后的序列的尾后迭代器。

 

智能指针原理及实现- unique_ptr

只允许基础指针的一个所有者。 可以移到新所有者(具有移动语义),但不会复制或共享(即我们无法得到指向同一个对象的两个unique_ptr)。 替换已弃用的 auto_ptr。 相较于 boost::scoped_ptr。 unique_ptr 小巧高效;大小等同于一个指针,支持 rvalue 引用,从而可实现快速插入和对 STL 集合的检索。在头文件<memory>中。

unique_ptr

为了避免和库里面的名称混淆,我自己实现的时候用的UniquePtr加以区分。

同一时刻,只能有一个unique_ptr指向某个内存区域,所以他是禁止拷贝的。unique_ptr本身是个对象,他生命周期结束时,会自动调用~unique_ptr(),将其所指对象销毁。

主要有这几个功能:

1、能写出异常安全的代码

2、

以上是关于C++ STL Unique 底层实现原理的主要内容,如果未能解决你的问题,请参考以下文章

浅谈 C++之 STL

智能指针原理及实现- unique_ptr

C++面试八股文快问快答のSTL篇

C++ STL的基本基本原理

超详细STL之基于源码剖析vector实现原理及注意事项

超详细STL之基于源码剖析vector实现原理及注意事项