• 《C++ Primer》学习笔记【第二部分 C++标准库】


    第8章 IO库

    IO对象不能复制,即1.IO对象不能存储在vector或其他容器中   2.如果需要传递或返回IO对象,必须传递或返回指向该对象的指针或引用。

    一般情况下,如果要传递IO对象以便对它进行读写,用非const引用的方式传递这个流对象。(因为要对IO对象进行读写)

    条件状态:IO标准库管理一系列条件状态成员,用来标记给定的IO对象是否处于可用状态,或碰到了哪种特定的错误。流的状态由bad、fail、eof和good操作揭示;clear和setstate操作用于改变条件成员的状态。

    输出缓冲区的管理:以下几种情况将导致缓冲区的内容被刷新。

     1.程序正常结束时,清空所有输出缓冲区。

     2.在一些不确定的时候,缓冲区可能已经满了,缓冲区会在下一个值之前刷新。

     3.用操作符显示刷新缓冲区,如endl。

     4.每次输出操作执行完后,用unitbuf操纵符设置流的内部状态,清空缓冲区。

     5.将输出流和输入流关联(用tie函数)起来。在此情况下,在读输入流时刷新其关联的输出缓冲区。标准库将cin和cout绑在一起。

     (如果程序崩溃,则不会刷新缓冲区,最好的方法是保证所有的输出操作都显式地调用了flush或endl; 交互式系统通常应确保它们的输入和输出流是绑在一起的)

    文件的输入与输出:

     如果要把fstream对象与另一个不同的文件关联,则必须先close现在的文件,再open另一个文件。

     考虑如何使用循环语句打开一些文件?

    //files是一个vector对象,包含一些要打开并读取的文件名
    //每次循环构造一个名为input的ifstream的对象
    while(it != files.end()){
        ifstream input(it->c_str());
        if(!input) break;
        while(input >> s) process(s);
        ++it;
    }
    //也可将input定义移到while外,那么需要更仔细地管理流对象。
    //每次需要打开新文件,故要关闭当前的文件流
    //关闭流不能改变流的内部状态,如果读写操作失败,状态将保持为错误模式,故需要调用clear
    ifstream input;
    vector<string>::const_iterator it = files.begin();
    while(it != files.end()){
        input.open(it->c_str());
        if(!input) break;
        while(input >> s) process(s);
        input.close();
        input.clear();
        ++it;
    }

    文件模式:....(此坑待填)

    字符串流:

    //1.如何每次读入一行,并分别处理每行中的每个单词
    string line, word;
    while(getline(cin, line)){
        istringstream stream(line);
        while(stream >> word){
            // do sth
        }
    }
    //2.stringstream提供的转换和/或格式化
    //一般情况下,使用输入操作符读取string时,空白符会忽略。
    int val1 = 512, val2 = 1024;
    ostringstream format_message;
    format_message << "val1: " << val1 << "
    " 
                   << "val2: " << val2 << "
    ";
    istringstream input_istring(format_message.str());
    string dump;
    input_istring >> dump >> val1 >> dump >> val2;
    cout << val1 << " " << val2 << endl;

    第9章 顺序容器

    赋值和swap:

    赋值相关运算会导致指向左边容器内部的迭代器、引用和指针失效,而swap操作将容器内容交换,迭代器、引用和指针不会失效。(array和string除外)

    除array外,swap不对任何元素进行拷贝、删除或插入操作,因此可以保证常数时间内完成。

    swap两个array会真正交换他们的元素,但指针、引用和迭代器所绑定的元素保存不变。

    网摘string的swap

     1 template<class _Elem,  
     2     class _Traits,  
     3     class _Alloc> inline  
     4     void __CLRCALL_OR_CDECL swap(basic_string<_Elem, _Traits, _Alloc>& _Left,  
     5         basic_string<_Elem, _Traits, _Alloc>& _Right)  
     6     {   // swap _Left and _Right strings  
     7         _Left.swap(_Right);  
     8     }  
     9     void __CLR_OR_THIS_CALL swap(_Myt& _Right)  
    10     {   // exchange contents with _Right  
    11         if (this == &_Right)  
    12             ;   // same object, do nothing  
    13         else if (_Mybase::_Alval == _Right._Alval)  
    14             {   // same allocator, swap control information  
    15  #if _HAS_ITERATOR_DEBUGGING  
    16             this->_Swap_all(_Right);  
    17  #endif /* _HAS_ITERATOR_DEBUGGING */  
    18             _Bxty _Tbx = _Bx;  
    19             _Bx = _Right._Bx, _Right._Bx = _Tbx;  
    20             size_type _Tlen = _Mysize;  
    21             _Mysize = _Right._Mysize, _Right._Mysize = _Tlen;  
    22             size_type _Tres = _Myres;  
    23             _Myres = _Right._Myres, _Right._Myres = _Tres;  
    24             }  
    25         else  
    26             {   // different allocator, do multiple assigns  
    27             _Myt _Tmp = *this;  
    28             *this = _Right;  
    29             _Right = _Tmp;  
    30             }  
    31     } 
    View Code

    网摘vector的swap

     1 template<class _Ty,  
     2     class _Alloc> inline  
     3     void swap(vector<_Ty, _Alloc>& _Left, vector<_Ty, _Alloc>& _Right)  
     4     {   // swap _Left and _Right vectors  
     5         _Left.swap(_Right);  
     6     }  
     7     void swap(_Myt& _Right)  
     8     {   // exchange contents with _Right  
     9         if (this == &_Right)  
    10             ;   // same object, do nothing  
    11         else if (this->_Alval == _Right._Alval)  
    12             {   // same allocator, swap control information  
    13  #if _HAS_ITERATOR_DEBUGGING  
    14             this->_Swap_all(_Right);  
    15  #endif /* _HAS_ITERATOR_DEBUGGING */  
    16             this->_Swap_aux(_Right);  
    17             _STD swap(_Myfirst, _Right._Myfirst);  
    18             _STD swap(_Mylast, _Right._Mylast);  
    19             _STD swap(_Myend, _Right._Myend);  
    20             }  
    21         else  
    22             {   // different allocator, do multiple assigns  
    23             this->_Swap_aux(_Right);  
    24             _Myt _Ts = *this;  
    25             *this = _Right;  
    26             _Right = _Ts;  
    27             }  
    28     } 
    View Code

    访问元素: 访问成员函数和下标操作返回的都是引用,如果容器是const容器,则返回const引用。

    迭代器失效:

    对于vector和string,存储空间被重新分配则迭代器、引用和指针失效。

    对于deque,插入删除首尾位置外的任何位置则迭代器、引用和指针失效,在首尾位置添加元素,迭代器会失效,但指向已存在的元素的引用和指针不会失效。

    对于list和forward_list,迭代器、引用和指针仍有效。

    第10章 泛型算法

    再探迭代器:

    插入迭代器,back_inserter, front_inserter, inserter, it是插入迭代器,属于迭代器适配器,it = t在it指定位置插入t并自动调整it指向的位置

     1 int main(){
     2     vector<int> ve;
     3     deque<int> de;
     4     auto it = back_inserter(ve);
     5     auto it2 = front_inserter(de);
     6     for(int i = 0; i < 5; i++)
     7         it = i, it2 = i;
     8 
     9     for(auto& e: ve)
    10         cout << e << ' ';
    11     cout << endl;
    12 
    13     for(auto& e: de)
    14         cout << e << ' ';
    15     cout << endl;
    16 
    17     auto it3 = inserter(ve, --ve.end());
    18     for(int i = 100; i < 500; i+=100)
    19         it3 = i;
    20     for(auto& e: ve)
    21         cout << e << ' ';
    22     cout << endl;
    23     return 0;
    24 }
    25 /*
    26 0 1 2 3 4
    27 4 3 2 1 0
    28 0 1 2 3 100 200 300 400 4
    29 */
    View Code

    第11章 关联容器

    正常情况下,解引用一个迭代器所返回的类型和下标运算符返回的类型是一样的,map除外。map解引用返回value_type对象,即pair型,下标返回mapped_type对象,即值型。

    无序容器:不是基于比较符,而是通过哈希函数映射到桶。无序容器在存储上组织为一组桶,每个桶保存0个或多个元素。我们需要提供函数来替代==运算符和哈希计算函数。

    第12章 动态内存

    动态内存:

     int *p = new (nothrow) int; //如果分配失败,new返回空指针

     int *p0 = new int;//如果分配失败,new抛出std::bad_alloc

     int *p1 = new int();

     int *p2 = new int[10]();

    new分配一个数组时,得到的是数组元素类型的指针,而不是数组类型。因此不能对动态数组调用begin或end, 这些函数使用数组维度来返回首元素和尾后元素的指针,也不能用范围for语句

    new可以分配一个大小为0的数组,返回合法非空指针,保证与new返回的其他任何指针都不同。

    释放动态数组不加[]和释放单一对象加[]都是未定义的。

    malloc与new有什么区别?

    前者是函数,不含构造函数,返回void。后者是运算符,含构造函数,返回类型。

    智能指针:此坑待填

    allocator类:

    new将内存分配和对象构造组合在一起,delete将对象析构和内存释放组合在一起。

    分配单个对象时通常希望将内存分配和对象初始化组合在一起;当分配一大块内存时,内存分配和对象初始化组合在一起往往会导致不必要的浪费。

    allocator使得内存分配和对象构造分离开来。allocator分配的内存是未构造的。

    allocator<T> a          //定义一个allocator对象,可以分配T类型
    a.allocate(n)           //分配n个未构造的T类型的内存
    a.deallocate(p, n)      //释放n个从p开始的内存,p必须是由allocate返回的指针,n必须是创建时的大小,调用前必须先对每个对象调用destroy
    a.construct(p, args)    //在p指向的内存中构造对象
    a.destroy(p)            //析构p指向的对象

    使用未构造的内存,行为是未定义的。

    当然,一个一个构造会很麻烦,标准库还为allocator类定义了两个伴随算法,拷贝和填充未初始化内存的算法。

  • 相关阅读:
    HUD 问题
    嵌入式面试
    网上某人面试经验总结
    C中prngtf是从右到左压栈的
    哈希表
    做事原则
    学习单片机的步骤
    C#预处理器命令
    CWinApp类CMultiDocTemplate类CDocument类CView类的关系
    Windows消息大全
  • 原文地址:https://www.cnblogs.com/dirge/p/6201188.html
Copyright © 2020-2023  润新知