namespace NamespaceIdentifier
{
// content of namespace here
}
NamespaceIdentifier::function(); // entering namespace
// add.h
#ifndef ADD_H
#define ADD_H
namespace BasicMath { int add(int x, int y); }
#endif
// add.cpp
#include "add.h"
namespace BasicMath
{
int add(int x, int y) // define the function add() inside namespace BasicMath
{
return x + y;
}
}
// main.cpp
#include "add.h" // for BasicMath::add()
int main()
{
std::cout << BasicMath::add(4, 3) << '\n';
}
namespace Foo
{
namespace Goo // Goo is a namespace inside the Foo namespace
{
int add(int x, int y) { return x + y; }
}
}
namespace Foo::Goo // Goo is a namespace inside the Foo namespace (C++17 style)
{
int add(int x, int y) { return x + y; }
}
namespace Active = Foo::Goo; // active now refers to Foo::Goo
std::cout << Active::add(1, 2) << '\n'; // This is really Foo::Goo::add()
int x { 2 }; // local variable, no linkage
{
int x { 3 }; // this declaration of x refers to a different object than the previous x
}
g_
to global variables is good practice.static int g_x{}; // non-constant globals have external linkage by default, but can be given internal linkage via the static keyword
const int g_y{ 1 }; // const globals have internal linkage by default
constexpr int g_z{ 2 }; // constexpr globals have internal linkage by default
int g_x { 2 }; // non-constant globals are external by default
extern constexpr int g_z { 3 }; // useless, needed forward declaration in another file
// different file
extern int g_x; // variable forward declaration
// constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
namespace constants // define your own namespace to hold constants
{
constexpr double pi { 3.14159 }; // constants have internal linkage by default
}
#endif
// constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
namespace constants
{
extern constexpr double pi { 3.14159 };
extern constexpr double avogadro { 6.0221413e23 };
}
#endif
// constants.h
#ifndef CONSTANTS_H
#define CONSTANTS_H
namespace constants
{
inline constexpr double pi { 3.14159 }; // note: now inline constexpr
inline constexpr double avogadro { 6.0221413e23 };
}
#endif
void incrementAndPrint()
{
static int s_value{ 1 }; // This initializer is only executed once.
++s_value;
std::cout << s_value << '\n';
} // s_value is not destroyed here, but becomes inaccessible because it goes out of scope
int main()
{
incrementAndPrint();
incrementAndPrint();
incrementAndPrint();
// Output: 2 3 4
}
Type | Example | Scope | Duration | Linkage | Notes |
---|---|---|---|---|---|
int x; |
Block | Automatic | None | ||
Static local variable | static int s_x; |
Block | Static | None | |
Dynamic local variable | int* x { new int{} }; |
Block | Dynamic | None | |
Function parameter | void foo(int x) |
Block | Automatic | None | |
Internal non-const global variable | static int g_x; |
Global | Static | Internal | Initialized or uninitialized |
External non-const global variable | int g_x; |
Global | Static | External | Initialized or uninitialized |
Inline non-const global variable (C++17) | inline int g_x; |
Global | Static | External | Initialized or uninitialized |
Internal constant global variable | constexpr int g_x { 1 }; |
Global | Static | Internal | Must be initialized |
External constant global variable | extern const int g_x { 1 }; |
Global | Static | External | Must be initialized |
Inline constant global variable (C++17) | inline constexpr int g_x { 1 }; |
Global | Static | External | Must be initialized |
extern
static
thread_local
mutable
auto
register
using
::
.
->
using std::cout; // this using declaration tells the compiler that cout should resolve to std::cout
#include <iostream>
namespace // unnamed namespace
{
void doSomething() // can only be accessed in this file
{
std::cout << "v1\n";
}
}
int main()
{
doSomething(); // we can call doSomething() without a namespace prefix
}
Much like an unnamed namespace, anything declared inside an inline namespace is considered part of the parent namespace. However, unlike unnamed namespaces, inline namespaces don’t affect linkage.
inline namespace V1 // declare an inline namespace named V1
{
void doSomething()
{
std::cout << "V1\n";
}
}
using namespace std::literals
).const
global variables if needed.