#c #static #object-lifetime
Вопрос:
В соответствии со стандартом:
5.13.5 Строковые литералы [лекс.строка]
16 Оценка строкового литерала приводит к объекту строкового литерала со статической длительностью хранения, инициализированному из заданных символов, как указано выше. Являются ли все строковые литералы различными (то есть хранятся в неперекрывающихся объектах) и дают ли последовательные вычисления строкового литерала один и тот же или другой объект, не указано.
и:
6.6.4.1 Продолжительность статического хранения [basic.stc.static]
1 Все переменные, которые не имеют динамической продолжительности хранения, не имеют продолжительности хранения потоков и не являются локальными, имеют статическую продолжительность хранения. Хранение этих объектов должно продолжаться в течение всего срока действия программы
Я предполагаю, что безопасно хранить указатели на строковые литералы, что-то вроде:
struct Base
{
Base(const char* name)
: _name(name)
{
}
void print()
{
std::cout<<_name<<std::endl;
}
const char* _name = nullptr;
};
struct MyDerived : public Base
{
MyDerived () : Base("MyDerived")
{
}
};
Хорошо ли определен приведенный выше код? Есть ли какие-то темные уголки стандарта, о которых я должен знать?
Комментарии:
1. Да, это четко определено и безопасно. Просто убедитесь, что вы не пытаетесь изменить символы или освободить память, на которую указывают.
2. И не думайте , что после
const char* x = "abcd"; const char* y = "abcd";
x == y
этого это будет правдой.
Ответ №1:
Хорошо ли определен приведенный выше код?
ДА.
Есть ли какие-то темные уголки стандарта, о которых я должен знать?
Возможно, в стандарте нет темного угла, но одна проблема заключается в том, что у вас есть указатель, и вы допускаете создание Base
экземпляра и использование таким образом:
Base foo(nullptr);
foo.print();
От operator<<
:
«Поведение не определено, если s
является нулевым указателем».
Несколько более безопасный конструктор:
template<size_t N>
constexpr Base(const char(amp;name)[N]) : _name(name) {}
Я говорю несколько, потому что вы все еще можете это сделать:
auto Foo() {
const char scoped[] = "Fragile";
Base foo(scoped);
foo.print(); // OK
return foo;
} // "scoped" goes out of scope, "_name" is now dangling
int main() {
auto f = Foo();
f.print(); // UB
}