5

从 c++11 标准的第 7.3.4.2 节:

using-directive指定指定命名空间中的名称可以在using-directive出现在using- directive 之后的范围内使用。在非限定名称查找 (3.4.1) 期间,名称看起来好像它们是在最近的封闭命名空间中声明的,其中包含使用指令和指定命名空间。[注:在此上下文中,“包含”是指“直接或间接包含”。——尾注]

第二句和第三句究竟是什么意思?请举例。

这是我试图理解的代码:

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;
}

它打印“7 7”而不是“7 18”,如我所料。

抱歉打错了,程序实际上打印了“7 11”。

4

2 回答 2

5

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

于 2012-09-20T22:17:38.917 回答
3

消除未定义的行为:

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;
}

该标准的含义是在线

    int tmp = i + 11;

该名称i出现在“最近的封闭命名空间中,其中包含使用指令和指定的命名空间”;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;
        }
    }
}

在行int j = ii出现在 using 指令(即A::D)和指定的命名空间(A::B::C)最近的封闭命名空间中,即A. 因此,在A::Dusing 指令之后的 inside 以及 inside A::D::E,非限定名称i可以指A::B::C::i出现为A::i、遮蔽 any ::i、与 any 冲突A::i以及被 anyA::D::iA::D::E::i(within 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;
        }
    }
}

请注意,仅仅因为名称在非限定名称查找期间出现 A::i,并不意味着它确实存在;限定名称A::i将继续仅引用实际名称A::i(如果存在)。

于 2012-09-21T13:37:06.727 回答