EDIT: я обнаружил, что мой вопрос содержит парадокс. В своем коде я использовал расширенный список инициализаторов, который появился в C++11, но я хотел использовать только инструменты C++98. Извините, я слишком поздно заметил предупреждающее сообщение моего компилятора. Конечно, семантика перемещения решила бы мою проблему в C++11. Мой вопрос больше не имеет значения.
Я решил создать собственный класс owner_ptr
. Концепция заключается в том, что объект owner_ptr
имеет право собственности на динамически выделяемый объект (или объекты). Один и тот же объект не должен принадлежать более чем 1 owner_ptr
. Вот моя реализация:
#include <cstddef>
template <typename T>
class owner_ptr
{
T* ptr;
bool array;
public:
owner_ptr() : ptr(NULL) {} /* LINE 10 */
owner_ptr(T* ptr, bool isArray = false) : ptr(ptr), array(isArray) {} /* LINE 11 */
owner_ptr(owner_ptr<T>& orig) : ptr(orig.ptr), array(orig.array) /* LINE 12 */
{
orig.ptr = NULL;
}
~owner_ptr()
{
if (ptr != NULL)
{
if (!array)
{
delete ptr;
}
else
{
delete[] ptr;
}
}
}
owner_ptr& operator=(owner_ptr<T>& rvalue)
{
if (this != &rvalue)
{
this->~owner_ptr();
ptr = rvalue.ptr;
array = rvalue.array;
rvalue.ptr = NULL;
}
return *this;
}
void reset()
{
this->~owner_ptr();
ptr = NULL;
}
void addPtr(T* newPtr, bool isArray = false)
{
this->~owner_ptr();
ptr = newPtr;
array = isArray;
}
T& operator*() { return *ptr; }
const T& operator*() const { return *ptr; }
T* get() { return ptr; }
const T* get() const { return ptr; }
T* operator->() { return ptr; }
const T* operator->() const { return ptr; }
T& operator[](int i) { return ptr[i]; }
const T& operator[](int i) const { return ptr[i]; }
};
Я указал, что ответственность за создание допустимых owner_ptr
объектов, таких как:
owner_ptr<int> op1(new int);
owner_ptr<int> op2(new int[3], true);
owner_ptr<int> op3(op1);
owner_ptr<int> op4;
op4 = op3;
Он хорошо работает с одномерными массивами. Однако, когда я пытаюсь выделить двумерный массив, этот код не компилируется:
int main()
{
owner_ptr< owner_ptr<int> > test(new owner_ptr<int>[2]{ owner_ptr<int>(new int[5], true), owner_ptr<int>(new int[8], true) }, true); /* LINE 72 */
return 0;
}
Я получил следующие сообщения:
\main.cpp|72|error: no matching function for call to 'owner_ptr<int>::owner_ptr(owner_ptr<int>)'|
\main.cpp|72|note: candidates are:|
\main.cpp|12|note: owner_ptr<T>::owner_ptr(owner_ptr<T>&) [with T = int]|
\main.cpp|12|note: no known conversion for argument 1 from 'owner_ptr<int>' to 'owner_ptr<int>&'|
\main.cpp|11|note: owner_ptr<T>::owner_ptr(T*, bool) [with T = int]|
\main.cpp|11|note: no known conversion for argument 1 from 'owner_ptr<int>' to 'int*'|
\main.cpp|10|note: owner_ptr<T>::owner_ptr() [with T = int]|
\main.cpp|10|note: candidate expects 0 arguments, 1 provided|
\main.cpp|72|error: no matching function for call to 'owner_ptr<int>::owner_ptr(owner_ptr<int>)'|
\main.cpp|72|note: candidates are:|
\main.cpp|12|note: owner_ptr<T>::owner_ptr(owner_ptr<T>&) [with T = int]|
\main.cpp|12|note: no known conversion for argument 1 from 'owner_ptr<int>' to 'owner_ptr<int>&'|
\main.cpp|11|note: owner_ptr<T>::owner_ptr(T*, bool) [with T = int]|
\main.cpp|11|note: no known conversion for argument 1 from 'owner_ptr<int>' to 'int*'|
\main.cpp|10|note: owner_ptr<T>::owner_ptr() [with T = int]|
\main.cpp|10|note: candidate expects 0 arguments, 1 provided|
Это так странно. У меня есть следующие вопросы:
- Почему компилятор ищет функцию
owner_ptr<int>::owner_ptr(owner_ptr<int>)
? Такой конструктор-копия не имел бы смысла. - Почему нельзя преобразовать
'owner_ptr<int>'
в'owner_ptr<int>&'
? - Как я могу это исправить? Можно ли выделить многомерное (используя шаблон
owner_ptr
) только одну команду?
Я знаю, что это работает:
owner_ptr< owner_ptr<int> > test(new owner_ptr<int>[2], true);
test[0].addPtr(new int[5], true);
test[1].addPtr(new int[8], true);
Однако мне любопытно, можно ли это сделать одной командой.
ПРИМЕЧАНИЕ. Я делаю это в учебных целях. Это не производственный код. Поэтому, пожалуйста, не рекомендуйте мне использовать интеллектуальные указатели C++11.
isArray
параметр зверство для начала. - person Revolver_Ocelot   schedule 12.08.2017