• vector 简单实现(未用到模板类,元素类型只能为string)


    // Strvec.h

    #pragma
    once #include <iostream> #include <string> #include <memory> #include <utility> #include <initializer_list> // 实现简版vector,之所以说简版是因为此vector只能存string,没有使用模板 class StrVec { public: StrVec():elements(nullptr),first_free(nullptr),cap(nullptr){} // 默认构造函数,将指针初始化为空指针 StrVec(const StrVec& origin); // 拷贝构造函数 StrVec(const std::initializer_list<std::string>& strVec);
    StrVec
    & operator=(const StrVec& strVec); // 拷贝赋值运算符 ~StrVec(); // 析构函数 void push_back(const std::string& e); size_t size() const { return first_free - elements; }; // 已存储元素的数量,因为无需改变数据成员,所以声明为cosnt size_t capacity() const { return cap - elements; }; // 总内存大小 std::string* begin() const { return elements; }; std::string* end() const { return first_free; }; private: std::allocator<std::string> alloc; void chk_n_alloc() { if (size() == capacity())reallocate(); }; // 添加元素时使用 void reallocate(); // 重新分配内存 void free(); // 销毁元素并释放内存 // 工具函数,被构造拷贝函数,赋值运算符,析构函数使用 std::pair<std::string*, std::string*> alloc_n_copy(const std::string*, const std::string*); std::string* elements; std::string* first_free; std::string* cap; };
    // StrVet.cpp



    #include "StrVec.h" // 这里是移动而不是拷贝元素 void StrVec::reallocate() // 重新分配内存 { auto newSize = size() ? 2 * size() : 1; auto newMem = alloc.allocate(newSize); // 新分配内存是原来的2倍 auto dest = newMem; auto elem = elements; while (elem != first_free) { alloc.construct(dest++, std::move(*elem++)); // 这里使用string的移动构造函数而不是拷贝构造函数,可以提高性能 } free(); elements = newMem; first_free = dest; cap = elements + newSize; } void StrVec::free() // 销毁元素并释放内存 { // 不能传递给deallocate一个空指针,要保证容器中有元素才进行销毁 if (elements) { for (auto p = first_free; p != elements;) { alloc.destroy(--p); } alloc.deallocate(elements, cap-elements); } } // 工具函数,被构造拷贝函数,赋值运算符,析构函数使用 std::pair<std::string*, std::string*> StrVec::alloc_n_copy(const std::string* b, const std::string* e) { auto data = alloc.allocate(e - b); return { data, std::uninitialized_copy(b, e, data) }; } StrVec::StrVec(const StrVec& origin) // 拷贝构造函数 { auto d = alloc_n_copy(origin.begin(), origin.end()); elements = d.first; first_free = cap = d.second; } StrVec::StrVec(const std::initializer_list<std::string>& strvec) { size_t size = strvec.size(); auto data = alloc.allocate(2 * size); auto dest = data; auto elem = strvec.begin(); for (size_t i = 0; i < size; ++i) { alloc.construct(dest++, std::move(*elem++)); } elements = data; first_free = dest; cap = elements + size; } StrVec& StrVec::operator=(const StrVec& strvec) // 拷贝赋值运算符 { auto d = alloc_n_copy(strvec.begin(), strvec.end()); free(); // 释放原内存 elements = d.first; first_free = cap = d.second; return *this; } StrVec::~StrVec() // 析构函数 { free(); } void StrVec::push_back(const std::string& e) { chk_n_alloc(); // 保证有足够的空间添加元素 alloc.construct(first_free++, e); // 利用allocator的construct在已分配内存中构建新对象 }
  • 相关阅读:
    在批处理中调用JS操作MongoDB
    如何利用jQuery post传递含特殊字符的数据
    利用Spring.NET实现WCF的AOP编程
    C#操作MongoDB帮助类
    C#操作MongoDB数据库方法
    利用CORS配置实现jQuery对WebApi及MVC的跨域访问
    利用System.Drawing.Image类进行图片相关操作
    图片预览示例
    文件上传控件(input type='file')对文件类型的过滤
    sysstat工具包之mpstat
  • 原文地址:https://www.cnblogs.com/qiang-wei/p/12392229.html
Copyright © 2020-2023  润新知