为什么方法局部静态变量绑定到 class 而不是实例?
Why are method-local static variables bound to class and not to instances?
在这个class
struct A
{
...
void method()
{
static x=0;
x++;
...
}
}
对于 A 的每个实例,对 method()
的调用将为所有实例递增 x
。
我预计 x
会在仅调用 method()
的实例中递增,而不会影响任何其他实例的 x
。这有效地将方法局部静态变量绑定到 class,作为一个附带问题:为什么我不能有 class 级别的静态变量(只有 const 的),我希望它表现得像方法局部静态变量当前执行。
我知道我可以 'fix' 使用一些额外的代码,但仍然想了解这种行为的原因。
一些代码供那些想要查看行为的人使用:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
inline void PRINTSTRING(const std::string &s) { std::cout << s; std::cout.flush(); }
template<typename...T> void say(T...t) { std::stringstream ss{}; (ss<<...<<t); PRINTSTRING(ss.str()); }
template<typename...T> std::string says(T...t) { std::stringstream ss{}; (ss<<...<<t); return ss.str(); }
template<typename...T> bool sayerr(T...t) { say("Error: ", t...); return false; }
struct A { std::string sa{"A"}; void who() { static int a=0; a++; say(says(sa, " a=", a, "\n")); }};
std::vector<A*> AList{};
void killas() { while (!AList.empty()) { auto it=AList.begin(); delete (*it); AList.erase(it); }}
A* newa(const std::string &s) { A *pA=new A; if (pA) { pA->sa=s; AList.push_back(pA); } return pA; }
void showas() { if (AList.empty()) say("-empty-\n"); else for (auto p:AList) p->who(); }
int main(int argc, const char *argv[])
{
say("\ntesting if a static var in a method is bound to instance or to class ...\n\nexpect 'empty'\n");
showas();
newa("one"); newa("two"); newa("three"); newa("four"); newa("five");
say("\nif bound to instance expect all 1's\n");
showas();
say("\nif bound to instance expect all 2's\n");
showas();
killas();
return 0;
}
静态成员属于class不是实例,方法局部静态各种也是这样。您只需要一个普通的 class 私人会员。
发现 this 虽然没有解释行为的原因,但确实很好地描述了它的用途。
另外关于 storage duration 它说:
Variables declared at block scope with the specifier static or
thread_local
(since C++11) have static or thread (since C++11)
storage duration but are
initialized the first time control
passes through their declaration (unless their
initialization is
zero- or constant-initialization, which can be performed before
the block is first entered). On all further calls, the declaration is
skipped.
更进一步:
Function-local static objects in all definitions of the same inline
function
(which may be implicitly inline) all refer to the same
object defined in one
translation unit.
我不知道这一点,现在知道它肯定有助于防止在我的代码中出现意外 'features'。
在这个class
struct A
{
...
void method()
{
static x=0;
x++;
...
}
}
对于 A 的每个实例,对 method()
的调用将为所有实例递增 x
。
我预计 x
会在仅调用 method()
的实例中递增,而不会影响任何其他实例的 x
。这有效地将方法局部静态变量绑定到 class,作为一个附带问题:为什么我不能有 class 级别的静态变量(只有 const 的),我希望它表现得像方法局部静态变量当前执行。
我知道我可以 'fix' 使用一些额外的代码,但仍然想了解这种行为的原因。
一些代码供那些想要查看行为的人使用:
#include <iostream>
#include <string>
#include <sstream>
#include <vector>
inline void PRINTSTRING(const std::string &s) { std::cout << s; std::cout.flush(); }
template<typename...T> void say(T...t) { std::stringstream ss{}; (ss<<...<<t); PRINTSTRING(ss.str()); }
template<typename...T> std::string says(T...t) { std::stringstream ss{}; (ss<<...<<t); return ss.str(); }
template<typename...T> bool sayerr(T...t) { say("Error: ", t...); return false; }
struct A { std::string sa{"A"}; void who() { static int a=0; a++; say(says(sa, " a=", a, "\n")); }};
std::vector<A*> AList{};
void killas() { while (!AList.empty()) { auto it=AList.begin(); delete (*it); AList.erase(it); }}
A* newa(const std::string &s) { A *pA=new A; if (pA) { pA->sa=s; AList.push_back(pA); } return pA; }
void showas() { if (AList.empty()) say("-empty-\n"); else for (auto p:AList) p->who(); }
int main(int argc, const char *argv[])
{
say("\ntesting if a static var in a method is bound to instance or to class ...\n\nexpect 'empty'\n");
showas();
newa("one"); newa("two"); newa("three"); newa("four"); newa("five");
say("\nif bound to instance expect all 1's\n");
showas();
say("\nif bound to instance expect all 2's\n");
showas();
killas();
return 0;
}
静态成员属于class不是实例,方法局部静态各种也是这样。您只需要一个普通的 class 私人会员。
发现 this 虽然没有解释行为的原因,但确实很好地描述了它的用途。
另外关于 storage duration 它说:
Variables declared at block scope with the specifier static or thread_local
(since C++11) have static or thread (since C++11) storage duration but are
initialized the first time control passes through their declaration (unless their
initialization is zero- or constant-initialization, which can be performed before
the block is first entered). On all further calls, the declaration is skipped.
更进一步:
Function-local static objects in all definitions of the same inline function
(which may be implicitly inline) all refer to the same object defined in one
translation unit.
我不知道这一点,现在知道它肯定有助于防止在我的代码中出现意外 'features'。