在这个班上
struct A
{
...
void method()
{
static x=0;
x++;
...
}
}
对于A的每个实例,对method()
的调用将对所有实例递增x
。
我希望对于仅调用x
的实例,method()
会增加,而对于任何其他实例,不会影响x
。这有效地将方法局部静态变量绑定到该类,并且是一个附带问题:为什么我不能拥有类级别的静态变量(仅const的),我希望它表现得像当前方法局部静态变量那样。
我知道我可以用一些额外的代码“修复”此问题,但仍然想了解这种现象的原因。
一些想要查看行为的代码:
#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;
}
答案 0 :(得分:1)
静态成员属于类而不是实例,方法局部静态也是如此。您只需要一个普通的班级私人成员即可。
答案 1 :(得分:0)
发现this在没有解释这种行为的原因的同时,确实对其用法做了很好的描述。
也针对storage duration说:
在块范围内声明的变量带有说明符static或 thread_local
(自C ++ 11起)具有静态或线程(自C ++ 11起) 存储期限,但
首次进行了初始化控制 通过他们的声明(除非他们的
初始化是 零初始化或常量初始化,可以在
之前执行 首先输入该块)。在所有其他电话上,声明为 跳过了。
再进一步:
同一内联的所有定义中的函数局部静态对象 函数
(可能是隐式内联的)都引用相同的 在一个
转换单元中定义的对象。
我不知道这一点,现在知道它肯定会有助于防止代码中意外的“功能”。