Global const string & пахнет плохо для меня, это действительно безопасно? - PullRequest
11 голосов
/ 22 июня 2009

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

const string& SomeConstant = "This is some constant text";

Лично для меня это плохо пахнет, поскольку ссылка ссылается на то, что я предполагаю, является "анонимным" объектом, созданным из данного массива символов.

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

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


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


Кроме того, когда вы делаете это как локальный, он явно имеет другую область действия:

class A
{
    string _str;

public:
    A(const string& str) :
        _str(str)
    {
        cout << "Constructing A(" << _str << ")" << endl;
    }

    ~A()
    {
        cout << "Destructing A(" << _str << ")" << endl;
    }
};

void TestFun()
{
    A("Outer");
    cout << "Hi" << endl;
}

Показывает:

Построение A (Внешнее); Уничтожение А (Внешнего); Привет

Ответы [ 7 ]

14 голосов
/ 22 июня 2009

Это полностью законно. Он не будет уничтожен, пока не закончится программа.

РЕДАКТИРОВАТЬ: Да , это гарантировано:

"Все объекты, которые не имеют динамического срок хранения, нет потока срок хранения, а не местный иметь статическую продолжительность хранения. хранение для этих объектов будет длиться на время программы (3.6.2, 3.6.3). "

- 2008 Рабочий проект, Стандарт для языка программирования C ++ , § 3.7.1 с. 63

Как заметил Мартин, это не полный ответ. Типовой проект дальнейших примечаний (§ 12.2, с. 250-1):

"Созданы временные классы типа в различных контекстах: привязка значения к ссылке (8.5.3) [...] Даже когда создание временного объекта избегается (12,8), все семантическое ограничения должны соблюдаться, как если бы временный объект был создан. [...] Временные объекты уничтожены в качестве последнего шага в оценке полное выражение (1.9), что (лексически) содержит точку, где они были создано. [...] Есть два контекста в которых временные уничтожены в другая точка, чем конец полное выражение. [...] Второй контекст, когда ссылка связана временно. Временный к которому ссылка связана или временный, то есть полный объект подобъекта, на который ссылается связана сохраняется в течение всей жизни ссылка кроме как указано ниже. "

Я тестировал в g ++, если тебе от этого легче. ;)

11 голосов
/ 22 июня 2009

Да, это законно и законно.

const string& SomeConstant = "This is some constant text";

// Is equivalent too:

const string& SomeConstant = std::string("This is some constant text");

Таким образом, вы создаете временный объект.
Этот временный объект связан с const & и, следовательно, его время жизни увеличено до срока службы переменной, с которой он связан (т.е. дольше, чем выражение, в котором он был создан).

Это гарантировано стандартом.

Примечание:

Хотя это законно. Я бы не использовал это. Простым решением было бы преобразовать его в const std :: string.

Использование:

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

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

Дополнительные мысли:

Это, с другой стороны, не будет страдать от проблемы:

char const* SomeConstant = "This is some constant text";

И может использоваться в любой точке. Просто мысль.

6 голосов
/ 22 июня 2009

Это может быть законно, но все же ужасно. Оставьте ссылку!

const string SomeConstant = "This is some constant text";
4 голосов
/ 22 июня 2009

Это так же законно, как и безобразно.

2 голосов
/ 22 июня 2009

Допустимо расширять временную переменную с помощью ссылки const, она используется Александреску ScopeGaurd , см. Это превосходное объяснение Херба Саттера под названием Кандидат на "Самую важную const". «.

Учитывая это, данный конкретный случай является злоупотреблением этой функцией C ++, и ссылка должна быть удалена, оставляя простой const string.

0 голосов
/ 23 июня 2009

Ладно, ребята, поправьте меня, если я не в восторге, но вот мои выводы, прислушиваясь ко всем вашим превосходным ответам:

A) это синтаксически и логически законно, & продлевает срок действия временного / анонимного пользователя с запредельного уровня до срока действия ссылки. Я проверил это в VC ++ 7 с:

class A { 
    public: A() { cout << "constructing A" << endl; }
    public: ~A() { cout << "destructing A" << endl; }
};

void Foo()
{
    A();
    cout << "Foo" << endl;
}

void Bar()
{
    const A& someA = A();
    cout << "Bar" << endl;
}

int main()
{
    Foo();    // outputs constructing A, destructing A, Foo
    Bar();    // outputs constructing A, Bar, destructing A
    return 0;
}

B) Хотя это и законно, это может привести к некоторой путанице в отношении фактического срока службы, и ссылка в этих случаях не дает вам никакой выгоды объявлять его нереферентным, поэтому, вероятно, следует избегать ссылки и даже быть лишним пространством. Поскольку в этом нет никакой пользы, это ненужное запутывание.

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

Звук не так ли?

0 голосов
/ 22 июня 2009

Объявляя его как const (что означает, что его нельзя изменить), а затем делая его ссылкой, что подразумевает, что кто-то может его изменить, кажется, по меньшей мере, плохой формой. Кроме того, как я уверен, вы понимаете, глобальные переменные являются ПЛОХОЙ и редко необходимы.

...