﻿# V1068\. Do not define an unnamed namespace in a header file\.

Анализатор обнаружил анонимное пространство имен, объявленное в заголовочном файле\. Такой заголовочный файл создаёт копии символов с "внутренним связыванием" \(internal linkage\) в каждой единице трансляции, включающей этот заголовочный файл\. Это приводит к "раздуванию" объектных файлов, что может быть нежелательным поведением\.

Рассмотрим простой пример заголовочного файла с анонимным пространством имен:

```cpp
// utils.hpp
#pragma once
#include <iostream>

namespace
{
  int global_variable;
  void set_global_variable(int v)
  {
    std::cout << global_variable << std::endl;
    global_variable = v;
  }
}
```

Каждая единица трансляции при включении заголовочного файла 'utils\.hpp' получит свой экземпляр переменной 'global\_variable', не связанной с другими экземплярами и не доступной из других единиц трансляции\. Также будет сгенерировано несколько избыточных функций 'set\_global\_variable'\. До стандарта C\+\+17 такой код мог встречаться в header\-only библиотеках для того, чтобы не нарушать One Definition Rule при включении заголовочных файлов в несколько единиц трансляции\. Также подобный код может появиться из\-за неаккуратного рефакторинга, например, при переносе анонимного пространства имен из компилируемого файла в заголовочный файл\.

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

```cpp
namespace my_namespace
{
  int variable1; // namespace-scope non-const variable
                 // 'variable1' has external linkage

  namespace // <=
  {
    int variable2; // unnamed namespace applies 'static'
                   // 'variable2' has internal linkage
  }
}
```

Если необходимо создать ровно один экземпляр символа для header\-only библиотеки, то можно воспользоваться спецификатором 'inline' \(начиная с C\+\+17, действует и для переменных\):

```cpp
// utils.hpp
#pragma once
#include <iostream>

inline int global_variable; // ok since C++17

inline void set_global_variable(int v)
{
  std::cout << global_variable << std::endl;
  global_variable = v;
}
```

Если используется более ранняя версия стандарта, но библиотека не header\-only, то можно объявить символы как 'extern' в заголовочном файле и определить их в одном из юнитов трансляции:

```cpp
// utils.hpp
#pragma once

extern int global_variable;
void set_global_variable(int v); // functions implicitly 
                                 // have external linkage ('extern')
```



```cpp
// utils.cpp
#include "utils.hpp"
#include <iostream>

int global_variable;

void set_global_variable(int v)
{
  std::cout << global_variable << std::endl;
  global_variable = v;
}
```

В том случае, когда используется более старая версия стандарта, но библиотека должна быть header\-only, срабатывание можно подавить комментарием:

```cpp
// utils.hpp
#pragma once
#include <iostream>

namespace //-V1068
{
  int global_variable;
  void set_global_variable(int v)
  {
    std::cout << global_variable << std::endl;
    global_variable = v;
  }
}
```