2016-02-02 1 views
0

У меня есть string_view класс, который предназначен, чтобы быть заменой для std::string:Убедитесь, что string_view не переживет его объект строки

struct string_view { 
    /* implicit */ string_view(const std::string& s) : ptr_(s.c_str()), size_(s.size()) {} 
    // other ctors... 

    const char* ptr_; 
    size_t size_; 
}; 

Однако пока все нормально писать

void f(string_view sv); 
f(std::to_string(123)); 

string_view не может пережить временный строковый объект, это привело бы к UB (использование после освобождения)

string_view g(string_view sv) { return sv; } 
string_view sv = g(std::to_string(123)); 
sv[0]; 

Другого случай UB:

string_view sv = std::to_string(123); 
sv[0]; 

Есть ли способ поймать такие ошибки во время компиляции? (Помимо плагина Clang).

+4

Никогда не храните * строковый вид. Это не то, для чего. Используйте только временные представления для * просмотра * строки. –

+0

Ржавчина имеет время жизни в свое время. C++ - нет. Вы должны использовать/написать некоторый статический анализатор, чтобы уловить некоторые из этих злоупотреблений для C++. – Jarod42

+0

Основное использование представлений - это аргумент для функций, вместо передачи char [] вы передаете представление. не используйте что-то другое. –

ответ

1

Рассматривайте их как неуправляемые указатели или ссылки без прав (без эталонного продления жизни), потому что это то, что они есть.

Как и неуправляемые указатели и ссылки, программист несет ответственность за управление жизненным циклом.

Если вы хотите иметь неизменяемые строки коровы вместо std::string s в качестве базовой линии, вы можете написать подсчет ссылок string_view s, которые гарантируют, что их исходная строка выдержит их (во время выполнения). С небольшим количеством работы вы даже можете добавить автоматическую фрагментацию (когда менее X% исходной исходной строки остается «живой», начните ее демонтаж).

(Корова = копия при записи).

Основная неизменяемая строка коровы использует общий указатель на строку const std и реплицирует большую часть строк std для API только для чтения.

Чтобы записать строку коровы, вы вызываете .extract(), который возвращает записываемый std::string (либо копию, либо если строка коровы уникальна при перемещении).

Вы пишете на это std::string, изменив его, а затем верните его корову.

Затем добавьте строку коровы с концепцией представления, где она может представлять собой подмножество буфера. Затем добавьте в системы для автоматического фрагментации больших буферов, когда ссылаются только на небольшой процент (эта часть сложна, особенно делает это поточно-безопасным и обрабатывает случай 1-мегапиксельной строки, в которой есть миллион строк коровы, которые получают доступ к первые 10 байтов).

Этот подход дает вам «безопасные» строки и строковые представления.

+0

Мы застряли в std :: string, не так ли?Я думаю, что сделать это изменчивым было, в ретроспективе, ошибкой. –

Смежные вопросы