【C++ Server】六、STL基础

六、STL基础
1、一些只需要写一次的函数是非常适合用lambda函数(没有名字的函数)来实现的。

lambda可以作为local对象,也可以作为参数传入。lambda相当于是内联函数,效率高。

auto local = [](int a, int b){
    std::cout << a << b;
};
local(1, 2);

template<typename Func>
void test(Func f, int a, int b){
    f(a, b);
}
test([](int a, int b){
    std::cout << a << b;
    }, 1, 2);

int a = 1;
int b = 1;
auto local= [&](){
    std::cout << a << b;
};
local();

2、forward_list不支持size()函数。

3、std::array是直接在栈上分配内存的。
std::array<int,5> a;        // 里面的值是乱的
std::array<int,5> b = {};    // 里面的值是0
std::array<int,5> c = {1};    // 第一个值是1,其余的值是0

a.swap(b);    // 线性的时间复杂度
swap(a,b);    // 线性的时间复杂度

a[1];    // 不检查下标是否合法
a.at(1);// 检查下标是否合法,会抛异常.

a.data();// 得到数组的指针.

auto info = std::get<1>a;    // tuple的形式,和a[1]是一样的意思.

a.fill(0);    // 给所有的值赋值为0.

除array之外,其他容器的swap是非常高效的(只交换一些指针值).

4、std::vector里面不要存bool。因为,C++中,vector<bool>为了达到节省内存的目的,专门做了特化,大概方式就是用bit位来存储数组中的元素。代价就是,这个容器里面的内置类型乱掉了。
std::vector<bool> a;
a[0];    //类型并不是bool!!!

std::vector<float> a(10);        // 10个元素,值为0.0
std::vector<float> b(10,1.0f);    // 10个元素,值为1.0f

b.reserve(100);    // 分配100个元素的空间

b.assign(5, 1.0f); // 5个元素,值为1.0f
b.emplace(b.end(), 1.0f);// C++11
b.emplace_back(1.0f); // C++11

b.resize(5);    // 重新设置当前大小为5
b.resize(5, 1.0f);    // 重新设置当前大小为5,如果当前元素个数不足5个,则新增的那些值为1.0f。如果当前元素大于等于5个,那1.0f这个参数就用不上了。

b.clear();    // 容量不会变少,内存还是那么大。要把内存降下来的话,调用shrink_to_fit()函数建议系统去降,请求容器降低其容量和size匹配。
b.shrink_to_fit(); //c++11

emplace操作与push、insert的区别:
emplace成员函数利用传入的参数在容器管理的内存中直接构造元素;push与insert成员函数则是将传入的元素类型对象拷贝到容器中,或创建一个局部临时对象,并将其压入容器中。
注意:emplace函数的参数根据元素类型而变化,参数必须与元素类型的构造函数相匹配。
std::vector<MyClass> a;
a.emplace_back(MyClass(1)); // C++11

因此,建议用emplace,而不建议用insert。

在服务器编程中,从客户端收到的包可以用vector来存放。
先进先出的模型,也就是先收到的包要先发出去,可以用deque来存放。

5、std::list插入和删除不会造成迭代器失效。
std::list<float> a;
a.remove(1.0f);    // 删除所有值为1.0f的节点
a.remove_if([](auto v){ return v>100.0f; }); // v是list里面的元素的值.
a.reverse();    // 反转链表
a.sort();         // 从小到大排序.

std::list<float> b;
a.merge(b);    // 合并两个排好序的链表

a.unique();    // 删掉排好序的链表中的重复的元素

a.splice(a.begin(), b);    // 将链表b插入到a.begin的位置.

6、单向链表。
std::forward_list<float> a;
a.before_begin();    // 返回第一个元素的前一个位置
a.cbefore_begin();

a.insert_after(a.before_begin(), 10.0f); // 插入第一个元素.
a.erase_after(a.before_begin()); // 删除第一个元素.


// 在数字3前面插入一个元素
std::forward_list<int> a{1,2,3,4,5};
auto iter = a.before_begin();
for(int i=0; i<2; ++i)    ++iter;
a.insert_after(iter, 10);

7、容器里面如果存放的是weaked_ptr的时候,遍历的时候效率很慢。

8、对于set可以用count函数来判断一个东西是否存在于容器中,但是对于multiset应该用find函数。

std::set<float> a = {1,2,4,5,6};
auto lower = a.lower_bound(5); // 返回5的位置
if(lower != a.end()){
    if(*lower == 5){
        // ...
    }
}
auto lower1 = a.lower_bound(3); // 返回4的位置
auto upper1 = a.upper_bound(3); // 返回4的位置

auto lower2 = a.lower_bound(5); // 返回5的位置
auto upper2 = a.upper_bound(5); // 返回6的位置

auto er = a.equal_range(5); // 返回一个pair,其中first是lower_bound的结果,second是upper_bound的结果。

auto state = a.insert(100); // 返回一个pair<Iterator,bool>,插入成功与否看该pair的second。

自己实现set的第二个模板参数:
struct CompareAge{
    template<typename T>
    bool operator()(const T& t1, const T& t2) const{
        return t1.age() < t2.age();
    }
};
std::set<Person, CompareAge> a;

Person p;
a.find(p);    // 是通过CompareAge去查找的.
std::find(a.begin(), a.end(), p); // 是通过操作符==去查找的.

// 查找map中的某个元素
std::map<int> a;
auto findIter = a.find(10);
if(findIter != a.end()){
    ...
}

9、如果对顺序没有需求的话,建议用unordered_map/unordered_set,而不建议用map/set。

要自定义MyClass的hash算法才能用unordered_map/unordered_set:

template<class T> inline void hash_combine(std::size_t &seed, const T &v) {
    std::hash<T> hasher;
    seed ^= hasher(v) + 0x9e3779b9 + (seed << 6) + (seed >> 2);
}
namespace std {
    template<> struct hash<Position> {    // 模板的特化
        size_t operator()(const Position& p) const {
            auto key = hash<int>()(p.x());
            hash_combine(key, p.y());
            return key;
        }
    };
}

std::unordered_set<Position> a;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值