【STL标准库 & 范型编程】学习笔记(3):分配器之测试 & OOP(面向对象编程)与 GP(范型编程)、容器之间的实现与分类

63 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 12 天,点击查看活动详情

分配器之测试

目的:测试使用不同分配器的效果

// 来源老师课件
using namespace std;
const long ASIZE = 500000L;

//----------------------------------------------------
#include <iostream>
#include <cstdio>  //snprintf()
#include <cstdlib> //RAND_MAX
#include <cstring> //strlen(), memcpy()
#include <string>
using std::cin;
using std::cout;
using std::string;

long get_a_target_long()
{
    long target = 0;

    cout << "target (0~" << RAND_MAX << "): ";
    cin >> target;
    return target;
}

string get_a_target_string()
{
    long target = 0;
    char buf[10];

    cout << "target (0~" << RAND_MAX << "): ";
    cin >> target;
    snprintf(buf, 10, "%d", target);
    return string(buf);
}

int compareLongs(const void *a, const void *b)
{
    return (*(long *)a - *(long *)b);
}

int compareStrings(const void *a, const void *b)
{
    if (*(string *)a > *(string *)b)
        return 1;
    else if (*(string *)a < *(string *)b)
        return -1;
    else
        return 0;
}

//---------------------------------------------------
#include <list>
#include <stdexcept>
#include <string>
#include <cstdlib>   //abort()
#include <cstdio>    //snprintf()
#include <algorithm> //find()
#include <iostream>
#include <ctime>

#include <cstddef>
#include <memory> //內含 std::allocator
                  // 欲使用 std::allocator 以外的 allocator, 得自行 #include <ext\...>
#ifdef __GNUC__
#include <ext\array_allocator.h>
#include <ext\mt_allocator.h>
#include <ext\debug_allocator.h>
#include <ext\pool_allocator.h>
#include <ext\bitmap_allocator.h>
#include <ext\malloc_allocator.h>
#include <ext\new_allocator.h>
#endif

namespace jj20
{
    // pass A object to function template impl(),
    // 而 A 本身是個 class template, 帶有 type parameter T,
    // 那麼有無可能在 impl() 中抓出 T, 創建一個 list<T, A<T>> object?
    // 以下先暫時迴避上述疑問.

    void test_list_with_special_allocator()
    {
#ifdef __GNUC__
        cout << "\ntest_list_with_special_allocator().......... \n";

        // 不能在 switch case 中宣告,只好下面這樣. 				//1000000次
        list<string, allocator<string>> c1;                   // 3140
        list<string, __gnu_cxx::malloc_allocator<string>> c2; // 3110
        list<string, __gnu_cxx::new_allocator<string>> c3;    // 3156
        list<string, __gnu_cxx::__pool_alloc<string>> c4;     // 4922
        list<string, __gnu_cxx::__mt_alloc<string>> c5;       // 3297
        list<string, __gnu_cxx::bitmap_allocator<string>> c6; // 4781

        int choice;
        long value;

        cout << "select: "
             << " (1) std::allocator "
             << " (2) malloc_allocator "
             << " (3) new_allocator "
             << " (4) __pool_alloc "
             << " (5) __mt_alloc "
             << " (6) bitmap_allocator ";

        cin >> choice;
        if (choice != 0)
        {
            cout << "how many elements: ";
            cin >> value;
        }

        char buf[10];
        clock_t timeStart = clock();
        for (long i = 0; i < value; ++i)
        {
            try
            {
                snprintf(buf, 10, "%d", i);
                switch (choice)
                {
                case 1:
                    c1.push_back(string(buf));
                    break;
                case 2:
                    c2.push_back(string(buf));
                    break;
                case 3:
                    c3.push_back(string(buf));
                    break;
                case 4:
                    c4.push_back(string(buf));
                    break;
                case 5:
                    c5.push_back(string(buf));
                    break;
                case 6:
                    c6.push_back(string(buf));
                    break;
                default:
                    break;
                }
            }
            catch (exception &p)
            {
                cout << "i=" << i << " " << p.what() << endl;
                abort();
            }
        }
        cout << "a lot of push_back(), milli-seconds : " << (clock() - timeStart) << endl;

        // test all allocators' allocate() & deallocate();
        int *p;
        allocator<int> alloc1;
        p = alloc1.allocate(1);
        alloc1.deallocate(p, 1);

        __gnu_cxx::malloc_allocator<int> alloc2;
        p = alloc2.allocate(1);
        alloc2.deallocate(p, 1);

        __gnu_cxx::new_allocator<int> alloc3;
        p = alloc3.allocate(1);
        alloc3.deallocate(p, 1);

        __gnu_cxx::__pool_alloc<int> alloc4;
        p = alloc4.allocate(2);
        alloc4.deallocate(p, 2); // 我刻意令參數為 2, 但這有何意義!! 一次要 2 個 ints?

        __gnu_cxx::__mt_alloc<int> alloc5;
        p = alloc5.allocate(1);
        alloc5.deallocate(p, 1);

        __gnu_cxx::bitmap_allocator<int> alloc6;
        p = alloc6.allocate(3);
        alloc6.deallocate(p, 3); // 我刻意令參數為 3, 但這有何意義!! 一次要 3 個 ints?
#endif
    }
}
//---------------------------------------------------
#include <cstdlib> //rand() and RAND_MAX
int main(int argc, char **argv)
{
    jj20::test_list_with_special_allocator();
    return 0;
}

Node:

  • 我们应该专注于容器的使用,对于分配器的使用可以暂时不细了解
  • 对于需要小内存的,可以使用malloc/free or new/delete(更方便一点)

OOP

OOP企图将data与method关联在一起

在这里插入图片描述

GP

GP则是想将data与method分开

  • 比如使用全局函数sort可以对vector、deque等进行排序
  • 容器与算法各自专注自家的实现,通过迭代器iterator进行沟通
  • 所有的算法最终涉及元素本身的操作,无非就是比大小

需要准备的知识点

操作符重载

类模板

函数模板

成员模板

模板的特点

  • 泛化
  • 特化
  • 偏特化

容器之间的实现与分类

本图以缩排形式表示“基层与衍生层”的关系

这里所谓衍生,并非继承,而是复合 在这里插入图片描述