1. 程式人生 > >C++ string類的簡單實現 (2)

C++ string類的簡單實現 (2)

參考

分析

如果一個class帶有指標型別的資料成員,那麼請思考預設的copy ctorcopy assign是否合適。如果你需要深拷貝那麼預設的行為就不合適了(預設為淺拷貝)。並且如果你的編譯器支援c++11,可以考慮是否可以利用右值引用來提高效率,這時需要實現move ctormove assign(注意nonexcept的使用)。最後,當然別忘了dtor

原始碼

#include <stdint.h>
#include <stdio.h>
#include <utility>
#include <string.h>
#include <malloc.h> #include <iostream> #include <vector> class String { public: // ctor String() : data_(new char[1]) { std::cout << "default ctor this:" << std::hex << this << std::endl; data_[0] = '\0'; } String(const
char* str) : data_(new char[strlen(str) + 1]) { std::cout << "ctor witch const char* this:" << std::hex << this << std::endl; data_[0] = '\0'; strcpy(data_, str); } // copy ctor String(const String& rhs) noexcept : data_(new char[strlen
(rhs.data_) + 1]) { std::cout << "copy ctor this:" << std::hex << this << " rhs: " << std::hex << &rhs << std::endl; strcpy(data_, rhs.data_); } // copy assign String& operator= (const String& rhs) { String tmp(rhs); swap(tmp); return *this; } /* String& operator= (String rhs) { std::cout << "copy assign this:" << std::hex << this << " rhs: " << std::hex << &rhs << std::endl; swap(rhs); return *this; } //注意: //String s("hello"); //s = "world"; 會提示和move copy assign ambiguous */ // move ctor String(String&& rhs) noexcept : data_(rhs.data_) { std::cout << "move ctor this:" << std::hex << this << " rhs: " << std::hex << &rhs << std::endl; rhs.data_ = nullptr; } // move assign String& operator= (String&& rhs) { std::cout << "move assign this:" << std::hex << this << " rhs: " << std::hex << &rhs << std::endl; swap(rhs); return *this; } // dtor ~String() { std::cout << "dtor " << std::hex << this << std::endl; delete [] data_; } // swap void swap(String& rhs) { std::cout << "member swap this:" << std::hex << this << " rhs: " << std::hex << &rhs << std::endl; using std::swap; swap(data_, rhs.data_); } const char* c_str() const { return data_; } private: char* data_; }; void swap(String& lhs, String& rhs) { std::cout << "non-member swap" << std::endl; lhs.swap(rhs); } namespace std { template<> void swap<String>(String& lhs, String& rhs) { std::cout << "std::swap total template specialization" << std::endl; lhs.swap(rhs); } } std::ostream& operator<< (std::ostream& os, const String& s) { os << s.c_str(); return os; }

注意上面的class根據Effective C++ rule 25,實現了member-swap, non-member-swap以及std::swap的全特化版本。

在vector中使用

  String s0;
  String s1("hello");
  std::vector<String> svec;
  //svec.reserve(4); // 開啟此行分析有什麼變化
  //svec.resize(4);  
  std::cout << "size: "<< svec.size()  << " cap:"<< svec.capacity() << std::endl;
  svec.push_back(s0);
  std::cout << "size: "<< svec.size()  << " cap:"<< svec.capacity() << std::endl;
  svec.push_back(s1);
  std::cout << "size: "<< svec.size()  << " cap:"<< svec.capacity() << std::endl;
  svec.push_back(baz());
  std::cout << "size: "<< svec.size()  << " cap:"<< svec.capacity() << std::endl;
  svec.push_back("good job");
  std::cout << "size: "<< svec.size()  << " cap:"<< svec.capacity() << std::endl;
  return 0;

右值引用 和 nonexcept

move ctor在標明nonexcept時,才會被vector使用(在需要reallocation時),否則會使用copy ctor