Почему локальные переменные метода c привязаны к классу, а не к экземплярам? - PullRequest
0 голосов
/ 04 апреля 2020

В этом классе

struct A
{
    ...
    void method()
    {
        static x=0;
        x++;
        ...
    }
}

для каждого экземпляра A вызов method() будет увеличивать x для всех экземпляров.

Я ожидал увеличения x для экземпляра, в котором вызывается только method(), и не влияет на x для любого другого экземпляра. Это эффективно связывает локальную методическую переменную stati c с классом, и, как побочный вопрос: почему я не могу иметь переменные stati c уровня класса (только константы), которые, как я ожидаю, будут вести себя как метод- локальная переменная stati c в настоящее время.

Я знаю, что могу «исправить» это с помощью дополнительного кода, но все же хочу понять причину такого поведения.

Некоторый код для тех, кто хочу увидеть поведение:

#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;
}

Ответы [ 2 ]

1 голос
/ 04 апреля 2020

Stati c член относится к классу, а не к экземпляру, локальный метод c различным также похож на этот. Вам просто нужен обычный член частного класса.

0 голосов
/ 06 апреля 2020

Найдено это , которое, хотя и не объясняет причину такого поведения, дает хорошее описание его использования.

Также относительно длительности хранения говорится:

Переменные, объявленные в области блока с указателем stati c или thread_local (начиная с C ++ 11) имеют длительность хранения stati c или thread (начиная с C ++ 11), но инициализируется первый раз, когда контроль проходит через их декларацию (если их инициализация - нулевая или постоянная инициализация, которая может быть выполнена до блок вводится первым). При всех последующих вызовах объявление пропускается.

и чуть дальше:

Локальные функции-функции c объекты во всех определениях одной и той же встроенной функции (которые могут быть неявно встроенными) все ссылаются на один и тот же объект, определенный в одном единица перевода.

Я не знал об этом, и знание этого сейчас, безусловно, поможет предотвратить непреднамеренные «особенности» в моем коде.

...