Last active
March 27, 2021 14:57
-
-
Save grayed/c059bbf1ad9326102a339f49f2e3050c to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// https://gist.github.com/grayed | |
// Application Programming Interface (API) | |
#include <iostream> | |
#include <exception> | |
template<typename T> | |
class MyArray { | |
struct MyArrayData { | |
MyArrayData(size_t sz_) : p(new T[sz_]), sz(sz_), allocated(sz_), refcnt(1) { } | |
MyArrayData(T* p_, size_t sz_) : p(p_), sz(sz_), allocated(sz_), refcnt(1) {} | |
~MyArrayData() { delete[] p; } | |
T* p; | |
size_t sz, allocated, refcnt; | |
} *d; | |
public: | |
MyArray(size_t sz_ = 0) : d(new MyArrayData(sz_)) { } | |
MyArray(const MyArray<T>& other) : d(other.d) { | |
d->refcnt++; | |
} | |
// 1. Освобождение памяти | |
~MyArray() { | |
if (--d->refcnt == 0) | |
delete d; | |
} | |
// 2. Сложение массивов | |
MyArray<T> operator +(const MyArray<T>& other) const { | |
MyArray<T> result(d->sz + other.d->sz); | |
for (size_t i = 0; i < d->sz; i++) | |
result.d->p[i] = d->p[i]; | |
for (size_t i = 0; i < other.d->sz; i++) | |
result.d->p[d->sz + i] = other.d->p[i]; | |
return result; | |
} | |
// 3. Доступ к элементам массива (с изменением массива и без оного) | |
T operator[] (size_t i) const { | |
if (i >= d->sz) | |
throw std::invalid_argument("invalid index"); | |
return d->p[i]; | |
} | |
T& operator[] (size_t i) { | |
if (i >= d->sz) | |
resize(i + 1); | |
return d->p[i]; | |
} | |
size_t getSize() const { return d->sz; } | |
void resize(size_t newSize) { | |
if (newSize <= d->allocated && d->refcnt == 1) { | |
d->sz = newSize; | |
return; | |
} | |
std::cerr << "reallocating from " << d->allocated << " to " << newSize << std::endl; | |
// создать новый T[newSize] | |
auto newp = new T[newSize]; | |
// скопировать нужное количество элементов из p | |
for (size_t i = 0; i < d->sz; i++) | |
newp[i] = d->p[i]; | |
// освободить p | |
if (d->refcnt == 1) { | |
delete[] d->p; | |
d->p = newp; | |
d->sz = newSize; | |
d->allocated = newSize; | |
} else { | |
MyArrayData* newData = new MyArrayData(newp, newSize); | |
d->refcnt--; | |
d = newData; | |
} | |
} | |
}; | |
int main(int argc, char** argv) { | |
MyArray<int> arr1(123), arr2(33); | |
MyArray<int> foo = arr1; | |
arr1[12] = arr2[42]; | |
MyArray<int> arr3 = arr1 + arr2; | |
const MyArray<int>& aref = arr3; | |
MyArray<int>& aref2 = arr3; | |
aref2[3] = 3; | |
std::cout << "Result size: " << arr3.getSize() << std::endl; | |
aref2.resize(100); | |
std::cout << "Changed size: " << aref2.getSize() << std::endl; | |
aref2.resize(200); | |
std::cout << "Changed second time size: " << aref2.getSize() << std::endl; | |
std::cout << "First Element: " << aref[0] << std::endl; | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment