Как уже ответили, delete
должен быть в деструкторе.Тем не менее, правильное решение вашей проблемы - не делать управление памятью вручную в этом случае.Вы должны использовать std::unique_ptr
для своего m_str
члена:
std::unique_ptr<char_type[]> m_str;
Это освобождает вас от необходимости вручную new
и delete
.Это также помогает защитить от утечек памяти в случае исключений.Даже если вы delete
выделите все, что у вас есть, у вас все равно могут возникнуть утечки памяти, если между new
и delete
возникнет исключение.unique_ptr
помогает предотвратить утечку такого типа.
Вашему классу нужны только небольшие изменения:
template<typename char_type = char>
class StringT {
public:
StringT()
{}
explicit StringT(const char_type *str)
{
if (str != nullptr) {
size_t len = strlen(str);
m_str = std::make_unique<char_type[]>(len + 1);
strcpy(m_str.get(), str);
}
}
StringT(const StringT & other)
{
size_t len = 0;
if (other.m_str)
len = strlen(other.m_str.get());
m_str = std::make_unique<char_type[]>(len + 1);
strcpy(m_str.get(), other.m_str.get());
}
StringT(StringT && other) noexcept
{
m_str = std::move(other.m_str);
}
StringT & operator+=(const StringT &other)
{
if (other.m_str == nullptr)
return *this;
const size_t mysize{m_str ? strlen(m_str.get()) : 0};
const size_t osize{strlen(other.m_str.get())};
auto newStr = std::make_unique<char_type[]>(osize + mysize + 1);
newStr[0] = '\0';
if (m_str)
strcat(newStr.get(), m_str.get());
strcat(newStr.get(), other.m_str.get());
m_str = std::move(newStr);
return *this;
}
size_t length() const
{
if (!m_str)
return 0;
return strlen(m_str.get());
}
friend
std::ostream &operator<<(std::ostream &out, StringT<> &other)
{
if (other.m_str)
out << other.m_str.get();
return out;
}
private:
std::unique_ptr<char_type[]> m_str;
};
Вы заметите, что в new
или delete
нет вызововэтот кодm_str
автоматически удалит выделенную память при необходимости.