问题
I am trying to create an object using placement new
(I know to use smart pointers, this is just to learn). My code is as follows:
#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;
}
I have created a global array
named arr and another array
named arr
in B
. It seems like when I do my placement new
the arr
being used is from the class as I get what I think are linker errors.
Why is this happening? why isn't the global arr
being used? If i change the placement new
to use my renamed global array
it works. I think it has to do something with lookups
but I don't have a concrete answer.
回答1:
From the C++ 2017 Standard (12.2.3.2 Static data members)
2 The declaration of a non-inline static data member in its class definition is not a definition and may be of an incomplete type other than cv void. The definition for a static data member that is not defined inline in the class definition shall appear in a namespace scope enclosing the member’s class definition. In the definition at namespace scope, the name of the static data member shall be qualified by its class name using the :: operator. The initializer expression in the definition of a static data member is in the scope of its class (6.3.7).
So in this definition of the static data member
const A* B::a_obj = new(arr) A;
the unqualified name arr
is at first searched in the scope of the class B
. And the class B indeed declares such a name
static char arr[sizeof(A)];
If you want to use the name from the global namespace then use the qualified name
const A* B::a_obj = new(::arr) A;
Here is a demonstrative program
#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;
}
Its output is
A::n1 = 10
A::n2 = 20
回答2:
The reason arr is attribute to the class B and not the global scope is due to unqualified name lookup rules.
Specifically:
Static data member definition For a name used in the definition of a static data member, lookup proceeds the same way as for a name used in the definition of a member function.
Meaning:
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
If you are intrested you can see more information here: http://en.cppreference.com/w/cpp/language/unqualified_lookup
As people suggested to get what you want just use:
const A* B::a_obj = new(::arr) A;
来源:https://stackoverflow.com/questions/47311823/static-variable-shadowing-global