【C++笔记】十七、string类与智能指针

1.string类的构造方法

#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
    // 模板类string的构造方法
    
    //  1. 没有参数的构造方法
    string str1;
    str1 = "超人";
    cout << "str1 = " << str1 << endl;
    
    //  2. string(const char* s) 参数为常量的字符指针
    const char s[] = "hello world";
    string str2_1(s);
    cout << "str2_1 = " << str2_1 << endl;
    string str2_2("世界你好.");
    cout << "str2_2 = " << str2_2 << endl;
    
    //  3. string(size_type n, char c) :将n个c连成字符串
    string  str3(12, 'd');
    cout << "str3 = " << str3 << endl; // dddddddddddd
    
    //  4.  string(const string &str)  参数是string类型
    string str4(str2_1);
    cout << "str4 = " << str4 << endl;  // hello world
    
    //  5.  string(const char* s, size_type n)  //  截取s指向的字符串的前n个字符
    char greeting[] = "hello bill";
    string str5(greeting, 5);
    cout << "str5 = " << str5 << endl; // hello
    
    // 6. template<class Iter>string(Iter begin, Iter end)  //  截取begin和end之间的字符,不包括end
    string str6(greeting + 6, greeting + 10); //greeting指向“h”,+6后指向“b”
    string str6_1(&str2_1[0] + 1, &str2_1[0] + 5);
    
    cout << "str6 = " << str6 << endl;  // bill
    cout << "str6_1 = " << str6_1 << endl;  // ello
    
    //  7. string(const string& str, size_type pos, size_type npos) //参数1:字符串 参数2:截取开始的位置 参数3:截取长度,若此参数不指定,则截取到末尾
    string str7_1(str2_1, 6);
    cout << "str7_1 = " << str7_1 << endl; // world
    string str7_2(str2_1, 6, 2);
    cout << "str7_2 = " << str7_2 << endl; // wo
    
    //  8.(C++ 11)string(initialier_list<char> list) 参数为字符列表
    string str8_1 = {'H', 'a', 'c'};
    string str8_2 {'a','b','c'};
    cout << "str8_1 = " << str8_1 << endl;  // Hac
    cout << "str8_2 = " << str8_2 << endl;  // abc
    
    return 0;
}

2.输入string类型的值

#include <iostream>
using namespace std;

int main(int argc, const char * argv[]) {
    // 输入string类型的值
    char cInput[20];  // 字符数组
 //   cin >> cInput;   // 读一个单词,空格后的都不要了,因为cInput[20],所以输入单词的长度最大为19
 //   cin.getline(cInput, 20);    // 读一行,空格后的还要,  \n(回车)这个符号不要了
 //   cin.get(cInput, 20);        // 读一行  将 \n(回车)也加入到读取队列中
 //   cout << cInput << endl;
 //   cin.getline(cInput, 20, ':');
 //   cout << cInput << endl;
    string sInput;  // 字符串
   // cin >> sInput;                // 读一个单词
   // getline(cin, sInput);
   // cout << sInput << endl;         //  读一行
    getline(cin, sInput, ';');  // 定义了第三个参数后,输入结束不再以\n(空格)为标志,而是以第三个参数为标志
    cout << sInput << endl;
    return 0;
}

3.string值的比较和定位

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // string的基本功能
    //  1.  字符串的比较
    //  2.  字符串的定位

    //  1.  字符串的比较,先根据ASCII值,如果ASCII值都一样,再根据长度,
    string str1("hello");
    string str2("world");
    
    if(str1 > str2)
    {
        cout << "str1 > str2" << endl;
    }
    else if(str1 < str2)
    {
        cout << "str1 < str2" << endl; // str1 < str2
    }
    else
    {
        cout << "str1 == str2" << endl;
    }
    
    char str3[20] = "I love you.";
    if(str3 < str1)
    {
        cout << "str3 < str1" << endl; // str3 < str1,大写字符的ASCII比小写的小
    }
    
    //  2.  字符串的定位
    cout << string::npos << endl;  // 本系统允许输入字符串的最大值
    cout << "str1.find(\"l\") = " << str1.find("l") << endl; // 2  返回str1中第一个l的位置的索引(从0开始)
    cout << "str1.find(\"l\", 3) = " << str1.find("l", 3) << endl; // 3 从第三个(0开始数)位置开始搜索l
    if(str1.find("l", 4) == string::npos)
    {
        cout << "未查到字符串" << endl;
    }
    cout << "str1.find(\"l\", 4) = " << str1.find("l", 4) << endl; // "未查到字符串"
    
    cout << "str1.rfind(\"l\") = " << str1.rfind("l") << endl;  // 3  从后往前查找,返回该位置从前往后的索引
    //  查找参数值中每一个字符在原字符串中第一个出现的位置
    cout << "str2.find_first_of(\"hero\") = " << str2.find_first_of("hero") << endl;  // 1
    //  查找参数值中每一个字符在原字符串中第一个出现的位置(从右往左找)
    cout << "str2.find_last_of(\"hero\") = " << str2.find_last_of("hero") << endl;    // 2
    //  查找原字符串中的每一个字符,在参数值中,第一次不出现的位置
    cout << "str2.find_first_not_of(\"whero\") = " << str2.find_first_not_of("hero") << endl;  // 0
    
    return 0;
}

4.获取string的尺寸和分配的空间的大小

#include <iostream>
using namespace std;
int main(int argc, const char * argv[]) {
    // 获取string的尺寸和已分配内存空间的尺寸
    string empty;
    string small = "hello";
    string large = "获取string的尺寸和已分配内存空间的尺寸";
    
    cout << "empty size is " << empty.size() << endl;  // 0
    cout << "small size is " << small.size() << endl;  // 5(字节)
    cout << "large size is " << large.size() << endl;  // 54 16个汉字+string,每个汉字占3字节
    
    cout << "empty capacity is " << empty.capacity() << endl;  // 22 在不同的编译环境,初始的空间尺寸不一定
    cout << "small capacity is " << small.capacity() << endl;  // 22,small占用的不超过22
    cout << "large capacity is " << large.capacity() << endl;  // 63(分配的内存是16的倍数减1),比54大的16的倍数减一,就是63了
    
    empty.resize(80);  // 给empty设置尺寸 16 *6 = 96
    cout << "empty capacity is " << empty.capacity() << endl; // 95

    return 0;
}

5.智能指针的基本用法

#include <iostream>
using namespace std;

class MyClass
{
public:
    MyClass()
    {
        cout << "MyClass对象被创建." << endl;
    }
    ~MyClass()
    {
        cout << "MyClass对象被销毁." << endl;
    }
    string getName()
    {
        return "Bill";
    }
};

void process1()
{
    auto myClass1 = new MyClass();
    cout << myClass1->getName() << endl;
    int i = 10;
    if(i > 1)
    {
        throw "出错了"; //若在此处抛出了异常,则不会再执行下面的delete myClass1;,进而导致内存泄漏
    }
    delete myClass1;
}
void process2()
{
    auto_ptr<MyClass> myClass1(new MyClass()); // 后面不需要跟着delete来释放内存空间了
    cout << myClass1->getName() << endl; // 打印:MyClass对象被创建.  Bill  MyClass对象被销毁.         
}
void process3()
{
    shared_ptr<MyClass> myClass1(new MyClass()); 
    cout << myClass1->getName() << endl;  // 结果同上
}
void process4()
{
    unique_ptr<MyClass> myClass1(new MyClass());  
    cout << myClass1->getName() << endl;   // 结果同上
}

int main(int argc, const char * argv[]) {
// 智能指针的基本用法,当保存指针的变量释放了,那么这个指针指向的内存空间同样也会被释放
    
    //  C++ 98: auto_ptr
    //  C++ 11: shared_ptr、unique_ptr
    //process1();
   // process2();
   // process3();
    process4(); 
    
    return 0;
}

6.auto_ptr、shared_ptr和unique_ptr的区别和应用场景

#include <iostream>
using namespace std;

void process1()
{
    auto_ptr<string> str1(new string("hello world")); // *str1是hello world
    auto_ptr<string> str2;
    str2 = str1;  //  所有权转移
    cout << *str2 << endl;   //  输出*str1会抛出异常,因为所有权转移,str1所指向的对象指针为null
}
void process2()
{
    unique_ptr<string> str1(new string("hello world"));
    unique_ptr<string> str2;
  //  str2 = str1;  //  编译时就会出错
    cout << *str2 << endl;
}
void process3()
{
    shared_ptr<string> str1(new string("hello world"));
    shared_ptr<string> str2;
      str2 = str1;  
    cout << *str1 << endl;  // str1和str2都能打印hello world
}

int main(int argc, const char * argv[]) {
    // auto_ptr、shared_ptr和unique_ptr的区别和应用场景
    //process1();
    // 如果两个或多个指针同时指向一个内存区域,那么当这些指针释放时,这块内存区域就会被释放多次,为了解决这一问题有三种方法:
    //  1. 深度复制:复制智能指针时指针指向的对象一起复制
    //  2. 所有权(auto_ptr和unique_ptr):对于一个特定对象,同时只能有一个智能指针拥有它。如果发生智能指针赋值操作,所有权会转移
    //  3. 智能指针计数器(shared_ptr):一个特定对象可以被多个智能指针引用。智能指针维护一个智能指针计数器,如果某个指针过期,计数器
    //  就会减1. 直到计数器为0,智能指针指向的对象才会被释放。
    process3();
    return 0;
}

7.unique_ptr与临时右值

#include <iostream>
using namespace std;

unique_ptr<string> getString()  // 函数getString的返回值类型是指向string的智能指针
{
    unique_ptr<string> str(new string("女神"));
    return str;
}

int main(int argc, const char * argv[]) {
    // unique_ptr与临时右值;
    
    //  如果右侧值在当前作用域是永久的unique_ptr智能指针,不允许将其赋值给其他的智能指针,如果右侧是临时的智能指针,则允许赋值
    unique_ptr<string> str1(new string("超人"));
   // unique_ptr<string> str2 = str1;  // 会报错
    unique_ptr<string> str3 = getString();  // 等号右侧是函数的返回值(临时变量),可以赋值
    cout << *str3 << endl;
    return 0;
}

8.如何选择智能指针

#include <iostream>
using namespace std;

void sortStr(shared_ptr<string> strArray[], size_t size) // 字符串排序函数,参数2是数组长度
{
    for(size_t i = 0; i < size - 2; i++)
    {
        for(size_t j = 0; j < size -1 -i; j++)
        {
            if(*strArray[j] > *strArray[j + 1])
            {
                shared_ptr<string> tmp;
                tmp = strArray[j];
                strArray[j] = strArray[j + 1];
                strArray[j + 1] = tmp;
            }
        }
    }
}

int main(int argc, const char * argv[]) {
    
    // 如何选择智能指针
    //  auto_ptr、unique_ptr和shared_ptr
    //  auto_ptr并不建议使用
    
    shared_ptr<string> strArray[]{
         shared_ptr<string>(new string("abc")),
         shared_ptr<string>(new string("xyz")),
         shared_ptr<string>(new string("hero")),
         shared_ptr<string>(new string("ccc")),
         shared_ptr<string>(new string("bcd"))
    };
    
    size_t size = 5;
    sortStr(strArray, size);
    for(size_t i = 0; i < size;i++)
    {
        cout << *strArray[i] << endl;
    }
    
    return 0;
}
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DUANDAUNNN

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值