Skip to content

Latest commit

 

History

History
129 lines (113 loc) · 3.04 KB

File metadata and controls

129 lines (113 loc) · 3.04 KB

Global scope

int x = 3;

int main() {
	int x = 5;
	{
		int x = 2;
		std::cout << ::x;  // ::x - global variable
	}
}

Qualified ID

namespace N {
	int f(int x);
}
int N::f(int x) {  // Qualified ID
	...
}

Definitions

In informal terms, a nested-name-specifier is the part of the id that:

  • begins either at the very beginning of a qualified-id or after the initial scope resolution operator (::) if one appears at the very beginning of the id and
  • ends with the last scope resolution operator in the qualified-id.

Very informally, an id is either a qualified-id or an unqualified-id. If the id is a qualified-id, it is actually composed of two parts: a nested-name specifier followed by an unqualified-id.

Example

struct A {
    struct B {
        void F();
    };
};
  • A is an unqualified-id.
  • ::A is a qualified-id but has no nested-name-specifier.
  • A::B is a qualified-id and A:: is a nested-name-specifier.
  • ::A::B is a qualified-id and A:: is a nested-name-specifier.
  • A::B::F is a qualified-id and both B:: and A::B:: are nested-name-specifiers.
  • ::A::B::F is a qualified-id and both B:: and A::B:: are nested-name-specifiers.

Namespaces

  • using - механизм для более удобного обращения к неймспейсам
  • Также можно делать псевдонимы
namespace some_long_name {
  namespace another_name {
    int foo() {
      return 1;
    }
  }
}
namespace al = some_long_name::another_name;

int main() {
  std::cout << al::foo();
}

Point of declaration

The point of declaration for a name is immediately after its complete declarator and before its initializer... [3.3.2/1]

#include <iostream>

int foo(int* a) {
  *a = 0;
  return 1;
}

int main() {
  int a /*point of declaration*/ = foo(&a);
  std::cout << a << '\n';
  const int x = 4;
  {
    int x[x] /*point of declaration*/ = {1, 2, 3, 4};
    std::cout << "x[2] = " << x[2] << '\n';
  }
}
  • For example:
int x = 101;
{
    int x = x;
    std::cout << x << std::endl;  // garbage
}
  • Above code is equal to the below one:
int x = 101;
{
  int x;
  x = x; // Self assignment, assigns an indeterminate value.
  std::cout << x << std::endl;
}
  • Because:
int x = x; <--// Now, we have the new `x` which hides the older one, 
//   ^        // so it assigns itself to itself
//   |
//   +---// Point of declaration,
//       // here compiler knows everything to declare `x`.
//       // then declares it.
  • Also, this example shows the point of declaration for an enumerator
const int x = 12;
{
  enum { x = x };
//             ^
//             |
//             +---// Point of declaration
//                 // compiler has to reach to "}" then
//                 // there is just one `x`, the `x` of `const int x=12`
}
  • The enumerator x is initialized with the value of the constant x, namely 12.
  • Source