c ++ using指令的范围

Tho*_*eod 4 c++ standards namespaces using-directives c++11

从c ++ 11标准的7.3.4.2节:

一个using指令规定,在被提名的命名空间中的名字可以在该范围内使用using指令后出现using指令.在非限定名称查找(3.4.1)期间,名称看起来好像是在最近的封闭命名空间中声明的,其中包含using-directive和指定的命名空间.[注意:在此上下文中,"包含"表示"直接或间接包含". - 尾注]

第二句和第三句完全是什么意思?请举例.

这是我试图理解的代码:

namespace A
{
    int i = 7;
}
namespace B
{
    using namespace A;
    int i = i + 11;
}
int main(int argc, char * argv[])
{
    std::cout << A::i << " " << B::i << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

正如我所料,它打印"7 7"而不是"7 18".

抱歉打印错误,该程序实际打印"7 11".

Lil*_*ard 5

using代码中的语句无关紧要.B::iB::i评估初始化程序时的范围.你可以通过删除using声明来简单地证明这一点; 你的代码应该编译和运行相同.在任何情况下,B::i最终都是未定义的值,因为它取决于未初始化的值(即B::i评估初始化程序时的值).


eca*_*mur 4

消除未定义的行为:

namespace A
{
    int i = 7;
}
namespace B
{
    using namespace A;
    int tmp = i + 11;
    int i = tmp;
}
#include <iostream>
int main()
{
    std::cout << A::i << " " << B::i << std::endl;
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

该标准的含义是在该行

    int tmp = i + 11;
Run Code Online (Sandbox Code Playgroud)

该名称i出现在“最近的封闭命名空间,其中包含 using 指令和指定命名空间”;using -directive出现在,namespace B而指定的命名空间是namespace A; 最近的封闭命名空间是全局命名空间,因此i显示为::i。这意味着如果名称i已存在于全局命名空间中,则代码是不明确的。

对于更复杂的示例:

namespace A {
    namespace B {
        namespace C {
            int i = 4;
        }
    }
    namespace D {
        using namespace B::C;
        namespace E {
            int j = i;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在行 处int j = ii出现在 using 指令(即A::D)和指定命名空间(A::B::C)的最近封闭命名空间中,即A。因此,在A::Dusing 指令之后,以及在 中A::D::E,非限定名称i可以指A::B::C::i出现为A::i、遮蔽 any ::i、与 any 冲突A::i以及被 anyA::D::i或遮蔽A::D::E::i(在 内A::D::E):

int i = 1;                // shadowed by A::B::C::i appearing as A::i
namespace A {
    int i = 2;            // conflicts with A::B::C::i appearing as A::i
    namespace B {
        int i = 3;        // irrelevant
        namespace C {
            int i = 4;    // nominated; appears as A::i
        }
    }
    namespace D {
        int i = 5;        // shadows A::B::C::i appearing as A::i
        using namespace B::C;
        namespace E {
            int i = 6;    // shadows A::B::C::i appearing as A::i
            int j = i;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,仅仅因为该名称在非限定名称查找期间显示为 A::i,并不意味着它实际上存在。限定名称A::i将继续仅指实际名称A::i(如果存在)。