【发布时间】:2020-04-04 09:49:23
【问题描述】:
在这个班级
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;
}
【问题讨论】:
-
static表示静态存储:该函数的每次执行都使用相同的地址为x静态分配存储。就其在 asm 中的工作方式而言,它与全局 var 或文件范围的static完全相同,只是编译器只允许您从声明它的范围访问它。 -
如果方法定义可以为对象添加更多状态(每个实例数据),
sizeof(class T)将需要查看每个成员的定义,而不仅仅是声明函数,强制在.h文件中定义所有类成员函数。除非这种可能性仅限于类声明中定义的成员函数?但这也会很奇怪。如果你想要一个私有成员变量,声明一个成员变量。顺便说一句,你可以拥有类范围的非常量static成员变量,例如class foo { static int x; };你似乎认为你不能? godbolt.org/z/5kUfxG
标签: c++ class static instance language-design