[C++] Почему используются неназванные пространства имен и каковы их преимущества?


Answers

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

Это то же самое, что и способ C иметь статическую глобальную переменную или статическую функцию, но ее также можно использовать и для определения классов (и ее следует использовать, а не static в C ++).

Все анонимные пространства имен в одном файле рассматриваются как одно и то же пространство имен, и все анонимные пространства имен в разных файлах различны. Анонимное пространство имен эквивалентно:

namespace __unique_compiler_generated_identifer0x42 {
    ...
}
using namespace __unique_compiler_generated_identifer0x42;
Question

Я только что присоединился к новому программному проекту C ++, и я пытаюсь понять дизайн. В проекте часто используется неназванное пространство имен. Например, что-то вроде этого может произойти в файле определения класса:

// newusertype.cc
namespace {
  const int SIZE_OF_ARRAY_X;
  const int SIZE_OF_ARRAY_Y;
  bool getState(userType*,otherUserType*);
}

newusertype::newusertype(...) {...

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




Безымянное пространство имен ограничивает доступ класса, переменной, функции и объектов к файлу, в котором он определен. Функциональность пространства имен аналогична static ключевому слову в C / C ++.
static keyword ограничивает доступ глобальной переменной и функции к файлу, в котором они определены.
Существует разница между неназванным пространством имен и ключевым словом static из-за чего неназванное пространство имен имеет преимущество перед статикой. static ключевое слово может использоваться с переменной, функцией и объектами, но не с определенным пользователем классом.
Например:

static int x;  // Correct 

Но,

static class xyz {/*Body of class*/} //Wrong
static structure {/*Body of structure*/} //Wrong

Но то же самое можно сделать и с неназванным пространством имен. Например,

 namespace {
           class xyz {/*Body of class*/}
           static structure {/*Body of structure*/}
  } //Correct



В дополнение к другим ответам на этот вопрос использование анонимного пространства имен также может повысить производительность. Поскольку символам внутри пространства имен не требуется никакого внешнего связывания, компилятор более свободен для агрессивной оптимизации кода в пространстве имен. Например, функция, которая вызывается несколько раз один раз в цикле, может быть встроена без какого-либо влияния на размер кода.

Например, в моей системе следующий код занимает около 70% времени выполнения, если используется анонимное пространство имен (x86-64 gcc-4.6.3 и -O2; обратите внимание, что дополнительный код в add_val не позволяет компилятору включить это дважды).

#include <iostream>

namespace {
  double a;
  void b(double x)
  {
    a -= x;
  }
  void add_val(double x)
  {
    a += x;
    if(x==0.01) b(0);
    if(x==0.02) b(0.6);
    if(x==0.03) b(-0.1);
    if(x==0.04) b(0.4);
  }
}

int main()
{
  a = 0;
  for(int i=0; i<1000000000; ++i)
    {
      add_val(i*1e-10);
    }
  std::cout << a << '\n';
  return 0;
}