Динамический текстовый объект с конструктором копирования, тривиальным оператором присваивания и тривиальным деструктором

Мне было показано, что std::string не может быть вставлен в boost::lockfree::queue,

boost::lockfree::queue слишком ценный, чтобы отказаться, поэтому я думаю, что я мог бы использовать очень большую фиксированную длину chars для передачи данных в соответствии с требованиями (при условии, что это даже удовлетворяет, так как у меня возникают проблемы с изучением того, как удовлетворить эти требования), но это потребляет память, если я хочу большие сообщения.

Существует ли текстовый объект динамического размера с конструктором копирования, тривиальным оператором присваивания и тривиальным деструктором? Если так, то где? Если нет, пожалуйста, опишите, как это сделать.

2 ответа

Решение

Тип динамического размера с тривиальной копией ctor/dtor невозможен. Есть два решения вашей проблемы: использовать тип фиксированного размера или хранить указатели в очереди:

boost::lockfree::queue<std::string*> queue(some_size);
// push on via new
queue.push(new std::string("blah"));
// pop and delete
std::string* ptr;
if(queue.pop(ptr))
{
   delete ptr;
}

Существует ли текстовый объект динамического размера с конструктором копирования, тривиальным оператором присваивания и тривиальным деструктором?

Динамический размер, нет. Для чего-то, чтобы иметь тривиальный деструктор, требуется, чтобы деструктор объекта был неявным (или дефолтным), а любые нестатические объекты-члены также имели неявные (или дефолтные) деструкторы. Поскольку все, что выделяется динамически, потребует delete [] где-то вдоль линии в деструкторе вы не можете выполнить это ограничение.

Чтобы расширить вышесказанное, рассмотрим (очень урезанный) пример того, что происходит в std::string:

namespace std
{
    // Ignoring templates and std::basic_string for simplicity
    class string 
    {
    private:
        char* internal_;
        // Other fields

    public:
        string(const char* str)
          : internal_(new char[strlen(str) + 1])
        { }

    };
}

Посмотрим, что произойдет, если мы оставим деструктор по умолчанию: он уничтожит выделенный стек char * (то есть сам указатель, а не то, на что он указывает). Это может привести к утечке памяти, так как теперь мы выделили пространство, которое не имеет ссылок и, следовательно, никогда не может быть освобождено. Итак, нам нужно объявить деструктор:

~string()
{
    delete[] internal_;
}

Однако, делая это, деструктор становится определяемым пользователем и, следовательно, нетривиальным.

Это будет проблемой для всего, что распределяется динамически. Обратите внимание, что мы не можем это исправить, используя что-то вроде shared_ptr или vector<char> как переменная-член; даже если они могут быть выделены в нашем классе стека, они просто позаботятся об управлении памятью для нас: где-то на линии с ними, есть new [] и соответствующий delete [] следовательно, они будут иметь нетривиальные деструкторы.

Чтобы удовлетворить это, вам нужно использовать выделенный стек char массив. Это означает отсутствие динамического распределения и, следовательно, фиксированный размер.

Другие вопросы по тегам