我正在尝试使用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;
}
我在global array
中创建了一个名为arr的array
和另一个名为arr
的{{1}}。似乎当我执行B
时,正在使用的placement new
来自类,因为我认为是链接器错误。
为什么会这样?为什么不使用arr
?如果我更改global arr
以使用我重命名的placement new
,则可以使用。我认为它必须与global array
做点什么,但我没有具体的答案。
答案 0 :(得分:1)
来自C ++ 2017标准(12.2.3.2静态数据成员)
2在其类中声明非内联静态数据成员 定义不是定义,可能是其他类型的不完整定义 比cv void。静态数据成员的定义不是 类定义中的内联定义应出现在命名空间中 封闭成员类定义的范围。在定义中 命名空间范围,静态数据成员的名称应该是合格的 通过使用::运算符的类名。 初始化表达式 在静态数据成员的定义中是在其范围内 class (6.3.7)。
所以在这个静态数据成员的定义中
const A* B::a_obj = new(arr) A;
首先在类arr
的范围内搜索非限定名称B
。而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
答案 1 :(得分:1)
原因是arr属于B类,而不是全局范围是由于非限定名称查找规则。
具体来说:
静态数据成员定义用于定义a的名称 静态数据成员,查找的方式与使用的名称相同 成员函数的定义。
含义:
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;