Advertisement
chevengur

strong safety

Dec 6th, 2024
65
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.67 KB | None | 0 0
  1. #include <initializer_list>
  2. #include <iostream>
  3. template <typename T>
  4. class vector{
  5.  
  6. public:
  7.     vector(size_t size): sz_(size), arr_(new T[size]){
  8.         for(int i = 0; i < size; ++i){
  9.             arr_[i] = 0;
  10.         }
  11.     }
  12.  
  13.     vector(std::initializer_list<T> lst_): sz_(lst_.size()), arr_(new T[sz_]){
  14.         std::copy(lst_.begin(), lst_.end(), arr_); //заполняем elem_ элементами из списка инициализации elem_[i] = 25 и тд.
  15.     }
  16.  
  17.     void reserve(size_t newcap){
  18.  
  19.         if(newcap <= cap_){
  20.             return;
  21.         }
  22.  
  23.         T* newarr = reinterpret_cast<T*>(new char[newcap*sizeof(T)]); //Если нет reinter, то не получится добавить кроме char* ничего.
  24.         size_t index = 0;
  25.         try{
  26.             for(; index < sz_; ++index){
  27.                 //newarr[index] = arr_[index]; UB, потому что newarr - не инициализировано. а это ссылка.
  28.                 new(newarr + index) T(arr_[index]); //placementnew Вызвать конструктор типа по данному адресу.
  29.             }
  30.         } catch(...){
  31.             for(size_t oldindex = 0; oldindex < index; ++oldindex){
  32.                 (newarr+oldindex)->~T();
  33.             }
  34.             delete[] reinterpret_cast<char*>(newarr);
  35.             throw;
  36.         }
  37.             /*Компилятор попробует освободить память, на которую указывает (arr_ + index).
  38.             Но я никогда не выделял эту память через new, поэтому он не знает, как это сделать.*/
  39.         for(size_t index = 0; index < sz_; ++index){
  40.             (arr_+index)->~T(); // когда мы выделяем память вручную new char[] компилятор не сможет ими управлять, поэтому удалять приходится самостоятельно
  41.         }
  42.         delete[] reinterpret_cast<char*>(arr_); //Преобразует указатель arr_ обратно к типу char*, который указывает на исходный блок сырой памяти.
  43.                                                     //Указывает компилятору освободить всю выделенную память.
  44.         arr_ = newarr;
  45.         cap_ = newcap;
  46.         // memcpy запрещено, потому что не переживёт тип, который имеет тип поля ссылку на другое поле.
  47.     }
  48.  
  49.     void push_back(size_t value){
  50.         if(sz_ >= cap_){
  51.             reserve(sz_*2);
  52.  
  53.             T* newarr = reinterpret_cast<T*>(new char[cap_*sizeof(T)]);
  54.             try{
  55.                
  56.                 size_t index = 0;
  57.                 for(; index < sz_; ++index){
  58.                     new (arr_ + index) T(arr_[index]);
  59.                 }
  60.                 new (arr_+sz_) T(value);
  61.                
  62.             }catch(...){
  63.                 for(size_t oldindex = 0; oldindex < sz_; ++oldindex){
  64.                     (newarr+oldindex)->~T();
  65.                 }
  66.                 delete[] reinterpret_cast<char*>(newarr);
  67.                 throw;
  68.             }
  69.  
  70.             for(size_t index = 0; index < sz_; ++index){
  71.                     (newarr+index)->~T();
  72.             }
  73.             delete[] reinterpret_cast<char*>(newarr);
  74.            
  75.             arr_ = newarr;
  76.            
  77.         }
  78.         else{
  79.             new (arr_+sz_) T(value);
  80.         }
  81.         ++sz_;
  82.     }
  83.  
  84.     size_t size() const{
  85.         return sz_;
  86.     }
  87.  
  88. private:
  89.     size_t cap_;
  90.     size_t sz_;
  91.     T* arr_;
  92.  
  93. };
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement