【问题标题】:Static variable shadowing global静态变量阴影全局
【发布时间】:2018-04-28 22:31:45
【问题描述】:

我正在尝试使用placement new 创建一个对象(我知道使用智能指针,这只是为了学习)。我的代码如下:

#include <vector>
#include <iostream>
#include <memory>


using namespace std; // please excuse this

// if you change like 19 to arr1 (or any other var name) instead of arr and line 40 to arr1 then it works

struct A
{
    int in = 999;
    A()
    {cout << "A ctor\n";}
    ~A()
    {cout << "A dtor\n";}
};

char arr[sizeof(A)];

class B
{
    public:
    static char arr[sizeof(A)];

    const static A* a_obj;

    B()
    {
        cout << "B ctor\n";
        //cout << (a_obj->in) << endl;
    }
    ~B()
    {
        cout << "B dtor\n";
    }
};



const A* B::a_obj = new(arr) A;


int main()
{
    B g;
}

我创建了一个名为 arr 的 global array 和另一个名为 arrin Barray。当我做我的placement new 时,使用的arr 似乎来自类,因为我得到了我认为的链接器错误。

为什么会这样?为什么不使用global arr?如果我将placement new 更改为使用我重命名的global array 它可以工作。我认为这与lookups 有关系,但我没有具体的答案。

【问题讨论】:

  • 请分享链接器错误。
  • 请阅读good C++ book。它应该解释范围、它们之间的变量阴影以及如何解决它。解决它们的一种方法是范围解析运算符 (::),您可以通过它在全局范围内使用 arr,如下所示:::arr
  • 您可以使用::arrB::arr 消除歧义。

标签: c++ c++11 scope static initialization


【解决方案1】:

arr 是 B 类的属性而不是全局范围的原因是由于不合格的名称查找规则。

具体来说:

静态数据成员定义 静态数据成员,查找的方式与查询中使用的名称相同 成员函数的定义。

意思:

struct X {
    static int x;
    static const int n = 1; // found 1st
};
int n = 2; // found 2nd.
int X::x = n; // finds X::n, sets X::x to 1, not 2

如果您有兴趣,可以在此处查看更多信息: http://en.cppreference.com/w/cpp/language/unqualified_lookup

正如人们建议的那样,只需使用你想要的东西:

const A* B::a_obj = new(::arr) A;

【讨论】:

  • 谢谢,以为是这样,但完全不确定。
【解决方案2】:

来自 C++ 2017 标准(12.2.3.2 静态数据成员)

2 在其类中声明非内联静态数据成员 定义不是定义,可能是不完整的类型 比简历无效。非静态数据成员的定义 类定义中的内联定义应出现在命名空间中 包含成员的类定义的范围。在定义中 命名空间范围,静态数据成员的名称应被限定 使用 :: 运算符按其类名。 初始化表达式 在定义一个静态数据成员是在其范围内 类 (6.3.7)。

所以在这个静态数据成员的定义中

const A* B::a_obj = new(arr) A;

首先在类B 的范围内搜索不合格名称arr。而B类确实声明了这样一个名字

static char arr[sizeof(A)];

如果您想使用全局命名空间中的名称,请使用限定名称

const A* B::a_obj = new(::arr) A;

这是一个演示程序

#include <iostream>

struct A
{
    const static int N = 10;
    static int n1;
    static int n2;
};

const int N = 20;

int A::n1 = N;
int A::n2 = ::N;


int main() 
{
    std::cout << "A::n1 = " << A::n1 << std::endl;
    std::cout << "A::n2 = " << A::n2 << std::endl;

    return 0;
}

它的输出是

A::n1 = 10
A::n2 = 20

【讨论】:

  • 谢谢你这么详细的解释!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-06-12
  • 2014-04-02
  • 1970-01-01
  • 2022-01-28
  • 2020-05-30
  • 2012-10-04
  • 2013-04-27
相关资源
最近更新 更多