C++ 09STL+转换函数

一、标准模板库STL(standard template library)

STL是泛型编程的经典案例
泛型编程简介:泛型编程是一种编程范式,旨在实现可重用性、类型安全和抽象性。
它允许开发人员编写适用于多种数据类型的代码,而无需为每种数据类型编写重复代码
//https://www.cnblogs.com/shijingjing07/p/5593399.html

1.vector数组

#include <algorithm>

vector向量相当于一个数组
在内存中分配一块连续的内存空间进行存储。支持不指定vector大小的存储。
通常此默认的内存分配能完成大部分情况下的存储
优点:
    可以不指定大小,使用push_back、pop_back来进行动态操作
    随机访问方便,即支持[]操作符和vector.at()
    节省空间
缺点:
    在内部进行插入删除操作效率低
    只能在vector的最后进行push和pop,不能再vector的头进行push和pop
    当动态添加的数据超过vector默认分配的大小时要进行整体的重新分配、拷贝与释放
参考://https://www.cnblogs.com/Nonono-nw/p/3462183.html

eg:

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;

int main(void)
{
#if 1
    vector<int> myvec;

    myvec.push_back(123);
    myvec.push_back(34);
    myvec.push_back(64);

#if 0 
    for(int i=0;i<myvec.size();i++){
        cout<<myvec[i]<<",";
       // cout<<myvec.at(i)<<",";
    }
    cout<<endl;
#endif

    // 采用迭代器进行遍历
    for (auto iter = myvec.begin(); iter != myvec.end(); iter++)
    {
        cout << *iter << ",";
    }
    cout << endl;

    sort(myvec.begin(),myvec.end());

    //采用foreach 
    for(auto i:myvec){
        cout<<i<<",";
    }
    cout<<endl;


#if 0
    auto iter = myvec.begin(); 
    iter++;
    myvec.insert(iter, 100);   //执行插入

    for (auto iter = myvec.begin(); iter != myvec.end(); iter++)
    {
        cout << *iter << ",";
    }
    cout << endl;
#endif 


#endif

#if 0
    vector <string> myvec;

    myvec.push_back("abc");
    myvec.push_back("hello");
    myvec.push_back("world");

    myvec.pop_back();
    
    for(int i=0;i<myvec.size();i++){ 
        //cout<<myvec[i]<<",";
        cout<<myvec.at(i)<<",";
    }
    cout<<endl;
#endif

    return 0;
}

2.栈stack

#include <stack>

stack
    特点:后进先出
//https://blog.csdn.net/weixin_52341477/article/details/119250698

eg:

#include <iostream>
#include <stack>
using namespace std;

int main(void)
{
    stack <double> mystack;

    mystack.push(35.6);
    mystack.push(0.54);
    mystack.push(67.3);
    mystack.push(2.6);


#if 0
    cout<< mystack.top()<<endl;
    mystack.pop();
    cout<< mystack.top()<<endl;
#endif 

    while(!mystack.empty()){  //循环 出栈
        cout<< mystack.top()<<endl;
        mystack.pop();
    }

    return 0;
}

3.队列queue

queue
    特点:先进先出
//https://www.cnblogs.com/qingyuanjushi/p/5911090.html

eg:

#include <iostream>
#include <queue>
using namespace std;

int main(void)
{
    queue<int> myqueue;

    myqueue.push(43);
    myqueue.push(75);
    myqueue.push(23);
    myqueue.push(66);

#if 0
    cout<<myqueue.front()<<endl;
    myqueue.pop();
    cout<<myqueue.front()<<endl;
#endif

    while (!myqueue.empty())   //循环出队列
    {
        cout << myqueue.front() << endl;
        myqueue.pop();
    }

    return 0;
}

4.list链表

#include <list>

list 双向链表

每一个结点都包括一个信息快Info、一个前驱指针Pre、一个后驱指针Post。
    可以不分配必须的内存大小方便的进行添加和删除操作。使用的是非连续的内存空间进行存储。
优点:
    不使用连续内存完成动态操作
    在内部方便的进行插入和删除操作
    可在两端进行push、pop
缺点:
    不能进行内部的随机访问,即不支持[ ]操作符和vector.at()
    相对于verctor占用内存多
//https://blog.csdn.net/yas12345678/article/details/52601578/

eg:

#include <iostream>
#include <list>
using namespace std;


int main(void)
{
    list <int> mylist;

    //插入
    mylist.push_front(13);
    mylist.push_front(74);
    mylist.push_front(96);
    mylist.push_back(100);


    //删除
    // mylist.pop_back(); //尾删
    // mylist.pop_front(); //头删

    mylist.sort();
    
    mylist.reverse();

    for(auto iter = mylist.begin(); iter!= mylist.end(); iter++ ){
        cout<<*iter<<",";
    }
    cout<<endl;

    return 0;
}

小结:
如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector
如果你需要大量的插入和删除,而不关心随机存取,则应使用list

5.map

#include <map>

map的元素是成对的键值/实值,内部的元素依据其值自动排序,map内的相同数值的元素只能出现一次,
Multimap内可包含多个数值相同的元素,内部由二叉树实现(实际上基于红黑树(RB-tree)实现),便于查找。

//https://blog.csdn.net/yyhyyhy/article/details/124531264     

eg:

#include <iostream>
#include <map>
using namespace std;

int main(void)
{
    map <string, double> price;

    price["ruler"] = 2.6;
    price.insert({string("notebook"),14.5});
    price["pen"] = 5.3;

    string item;
    
    while(1){
        cin>>item;
        if(item=="quit"){
            break;
        }
        cout<<"该商品的价格:"<<price[item]<<endl;
    }

    return 0;
}

二、转换函数(类型转换)

1.隐式转换相关

在C++中也有类型转换的需求

基本数据类型,可以直接显示转换,或者隐式转换
c风格的转换     (int)3.51
C++风格的转换   int(3.51)
    
    
面向对象(自定义类) 的转换,需要写转换函数,然后便可以显示转换或隐式转换
基本语法: 
operator 类型( ) 
{
    实现转换的语句;
}
基本规则:
    转换函数只能是成员函数,无返回值,空参数。
    不能定义到void的转换,也不允许转换成数组或者函数类型。
    转换常定义为const形式,原因是它并不改变数据成员的值。    
类似于运算符重载,本质:重载
为了避免隐式转换(安全问题)explicit关键字用来修饰类转换函数, 
explicit 还可以修饰构造函数,避免隐式转换
    
转换函数 慎用

eg:

#include <iostream>
using namespace std;

class A
{
private:
    int val;                 
public:
    A(int x=0): val(x)  {       
    }
    void set_val(int x)  {        
        val = x;
    }
    void print_val(void) const { 
        cout<<"val:"<<val<<endl;
    }

    explicit operator int()  {
        return val;
    }

};

int main(void)
{
    A a1(534);
    a1.print_val();


     int  ret = (int)a1;  //把a1强转成 int类型  // A --> int
     cout<<ret<<endl;

    //有了转换函数,会大量出现编译器自动执行 隐式转换 (容易出现安全问题)
    //为了防止隐式转换,可以添加关键字explicit
    //explicit 也可以修饰构造函数,防止隐式转换


    cout<<(int)a1<<endl;  //只能显示转换

#if 0
    cout<<a1<<endl;

    A a2(54);
    A a3 = a2+a1;

    cout<<a3<<endl;
#endif 

#include <iostream>
using namespace std;

class A
{
private:
    int val;                 
public:
    explicit A(int x=0): val(x)  {        //修饰构造函数 防止隐式转换 更加安全 
    }
    void set_val(int x)  {        
        val = x;
    }
    void print_val(void) const { 
        cout<<"val:"<<val<<endl;
    }
};

#if 0
A fun(int i)
{
    return i;
}
#endif 

int main(void)
{
    A a1(534);
    a1.print_val();
    
#if 0
    A a2 = 33;       //隐式转换  A a2(33)
    a2.print_val();
#endif 
    //A a2=33;       //explicit 修饰构造函数,防止隐式转换

    A a3(33);

    return 0;
}

2.标准的转换函数:

C++提供了一些标准转换函数,建议使用标准转换函数进行类型转换
    分别有:reinterpret_castconst_caststatic_castdynamic_cast

1. reinterpret_cast<new type>(expression)
    将一个类型的指针转换为另一个类型的指针,它也允许从一个指针转换为整数类型
    
2. const_cast<  new type>( expression)
    const指针与普通指针间的相互转换,注意:不能将非常量指针变量转换为普通变量
    
3. static_cast<new type>(expression)
    主要用于基本类型间的相互转换,和具有继承关系间的类型转换
        
4. dynamic_cast<newtype>(expression)
    只有类中含有虚函数才能用dynamic_cast;仅能在继承类对象间转换
    dynamic_cast具有类型检查的功能,比static_cast更安全

注意:其实只有dynamic_cast,是具有安全检查的类型转换

#include <iostream>
using namespace std;

//多态: 同一接口,面向不同对象,调用的方法不同

class Animal
{
public:
    virtual void eat(){         
        cout<<"animal eat"<<endl;
    }
};
class Cat:public Animal
{
public:
    void eat(){
        cout<<"cat eat function"<<endl;
    }
};
class Dog:public Animal
{
public:
    void eat(){
        cout<<"dog eat function"<<endl;
    }
};




int main(void)
{

    Cat cat1;

    Animal *ptr = &cat1;

    //ptr->eat();
    Cat *p =  dynamic_cast<Cat *> (ptr);

    //在标准转换函数中,只有dynamic_cast,具有安全检查,其它的等同于强转 
    p->eat();


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值