Что делает создание структуры в анонимном пространстве имен?

Возможный дубликат:
Почему используются неназванные пространства имен и каковы их преимущества?

Просмотр кода someones, и это то, что они объявили:

namespace {

  struct myStruct {
     int x;
     int y;
  } obj1;

}

.. в функции, я вижу, он используется следующим образом:

myStruct& var = obj1;

(Уведомление namespace является анонимным.)

Из того, как я его вижу, я не могу понять, почему он объявлен и используется как это.

Что объявляет это так, как это делается по-другому?

Кроме того, почему здесь создан указатель, а не традиционный стиль показанный здесь. т.е. myStruct * ptr;

Спасибо!

Ответ 1

Все, что объявлено внутри анонимного пространства имен, получает уникальное, непознаваемое имя и, следовательно, нельзя ссылаться ни на одну другую единицу перевода. Таким образом, анонимное пространство имен будет локальным только для текущей единицы перевода и никогда не столкнуться с другим.

Например, если вы скажете namespace { int i; }, вам гарантируется, что только текущая единица перевода видит глобальный i. Даже если это объявление находится в заголовке, который включен в несколько разных TU, каждый TU получает свою собственную копию глобальной переменной (каждая с другим непознаваемым полностью квалифицированным именем).

Эффект был похож на объявление глобального объекта static (который дает внутреннюю связь глобального объекта) в С++ 03, где объекты в анонимном пространстве имен все еще могут иметь внешнюю связь. В С++ 11 имена в неназванном пространстве имен имеют внутреннюю привязку в соответствии с 3.5/4, поэтому эффект одинаково для переменных и функций, объявляющих их static – но внутренняя связь применяется не только к переменным и функциям (например, перечислениям, классам, шаблонам), поэтому с С++ 11 вы всегда должны отдавать предпочтение безымянным пространствам имен!

Ответ 2

В С++ вам разрешено иметь только одно определение в заданной именованной области. Если есть несколько единиц перевода, вам по-прежнему разрешено иметь только одно определение, но компилятор не гарантирует, что все определения действительно идентичны. То есть, если вам нужен локальный тип, например, struct или class, вам нужно убедиться, что определение не конфликтует с другим типом в любом месте в любой другой единицы перевода. Выполнение этого практически невозможно в большом проекте, если у вас нет способа как-то локально защитить ваш тип. Это то, что предоставляет неназванное пространство имен: любое имя, определенное в неназванном пространстве имен, является уникальным для всего исполняемого файла.

Ответ 3

Это в основном то же самое, что и ключевое слово static, но на самом деле не заставляет внутреннюю связь. Переменная по-прежнему внешне связана, у вас просто нет способа разрешить ее имя в любой другой единицы перевода. Это было необходимо, потому что аргументы шаблона должны иметь внешнюю связь или, по крайней мере, использоваться для этого.

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

Ответ 4

Кроме того, почему созданный таким образом указатель вместо традиционного стиля показан здесь. т.е. myStruct * ptr;

Это ссылка, а не указатель, созданный с помощью myStruct& var = obj1;. Тем не менее одно и то же обоснование применимо к указателям. Многие программисты на C++ предпочитают myStruct* ptr более myStruct *ptr, myStruct& ref более myStruct &ref. Компилятору все равно, что вы используете. Этот стиль предпочтительнее для читателя кода.

Причиной размещения звездочки или амперсанда с типом, а не с переменной является то, что эта звездочка или амперсанд логически является частью этого типа. Тип ptr - указатель на myStruct. По этой схеме возникает потенциальная проблема: Type* ptr1, ptr2; Из-за правил, унаследованных от C, ptr2 не является указателем. Это просто int.

Там легко решить эту проблему. Не делай этого! В общем, лучше объявить одну переменную для объявления, исключая для простых вещей, таких как int i,j,k; Не смешивать указатели и не указатели.