Подтвердить что ты не робот

Почему нет конструктора резервирования для std::string?

Существует несколько конструкторов для std::string. Я искал способ избежать перераспределения, и я удивлен тем, что есть конструктор заполнения, но конструктор "резервный".

 std::string (size_t n, char c);

но не

 std::string (size_t n);

Итак, мне нужно вызвать reserve() после того, как он уже присвоил значение по умолчанию (16 байтов в моем случае), чтобы сразу перераспределить его?

Есть ли причина, почему нет такого конструктора для резервирования пространства непосредственно, когда объект создается, вместо того, чтобы делать это вручную? Или я что-то упускаю, и есть способ сделать это?

Использование конструктора заливки - пустая трата времени, потому что он будет циклически перемещаться по памяти, чтобы получить перезапись, а также вызвать неправильный размер, потому что s.length() сообщает N вместо 0.

4b9b3361

Ответ 1

Это все догадки, но я постараюсь.

Если вы уже знаете размер строки, которая вам нужна, вы, скорее всего, будете копировать данные из другого места, например. из другой строки. В этом случае вы можете вызвать один из конструкторов, которые принимают char * или const std::string &, чтобы скопировать данные немедленно.

Кроме того, я не понимаю, почему использование reserve сразу после построения строки - это плохо. Хотя это определение реализации, я бы предположил, что это будет иметь смысл для этого кода:

std::string str;
str.reserve(100);

выделить память для всего 100 элементов, а не 116 (как в "сначала выделить 16, а затем освободить их и выделить еще 100" ), тем самым не влияя на производительность несуществующего конструктора резервных копий.

Кроме того, если вам просто нужна пустая строка без выделения по умолчанию, вы можете использовать std::string str(0, ' ');, которая делает недействительной точку "Использование конструктора заливки является пустой тратой времени".

Ответ 2

Одним из вариантов использования конструктора резерва может быть использование std::string со статическим /thread_local хранилищем для переменных кэша.

void function(){
   thread_local std::string str; // no reserving constructor defined
}

Для таких сценариев вы можете написать лямбда-функцию, которая создает std::string и резервирует желаемый объем памяти.

void function(){
    auto reserving_string_constr = [](std::size_t reserve_size){
        std::string str;
        str.reserve(reserve_size);
        return str;
    };
    thread_local std::string str(reserving_string_constr(128));
    /*...*/
}

Ответ 3

вы можете задать один и тот же вопрос о каждом методе std::string, который не является конструктором.

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

может быть много причин, чтобы не перегружать конструктор, который резервирует память. Я думаю, что в объектно-ориентированном множестве мысль о "зарезервированной строке памяти" немного нечетна. строка представляет последовательность символов, а не память позади нее - это детали реализации, а не основная функция.
Когда кто-то открывает нового ресторана, думает ли он себе:" Когда этот ресторан наконец откроется, в самый момент открытия я забронирую 100 сит для предполагаемой 100-местной группы, которая может или не придет!"

но ваш вопрос неявно говорит что-то очень короткое: отсутствие надлежащих объектов буфера в С++. вы спрашиваете о конструкторе резервирования, потому что вы хотите использовать строку в качестве буфера, но нуль-инициализация их очень дорогостоящая. резервирование памяти не позволит вам писать за пределами размера строки.
поэтому решение этой проблемы - использовать unique_ptr<char[]>, который не будет нулевым-инициализировать символы, но даст вам стиль RAII, который вы ищете.