(C++) Указатель на статическую переменную

Тема в разделе "Arduino & Shields", создана пользователем Mitrandir, 16 сен 2018.

  1. Mitrandir

    Mitrandir Гуру

    Есть такой код:

    Код (C++):
    struct Foo{
    uint8_t a;
    uint8_t b;
    uint8_t c;
    };

    Foo* getFoo(){
      static Foo foo;
      if (foo.a != 1){
        foo.a= 1;
        foo.b= 1;
        foo.c= 3;
      }
      return &foo;
    }

    void setup()
    {
       Serial.begin(9600);
       getFoo();
    }

    void loop()
    {
      Foo* fp = getFoo();

       fp->b++;
       Serial.println(fp->b);
    }


     
    Запустил, вроде как работает. считает от 0 до 255...
    У него есть какие нибудь подводные камни? или я параною?
     
  2. DetSimen

    DetSimen Guest

    foo это ненастоящая локальная переменная, она храница не в стеке, а в сегменте глобальных данных, как обычная глобальная переменная, патамуш надо хранить ее значение между вызовами. Единственное отличие от глобальной переменной, - область видимости, никто, кроме функции, ее содержащей, ее не видит. Ну а все, что храница в сегменте данных имеет постоянный адрес и если функция захочет им поделиться, кто ж ей посмеет отказать? Так что такая канструкция тоже имеет право на жизнь.
     
    Mitrandir нравится это.
  3. parovoZZ

    parovoZZ Гуру

    А для чо так хитро?
     
  4. DetSimen

    DetSimen Guest

    Например, сделать singleton.
    Код (C++):
    TObject *getObject() {
      static TObject *obj = NULL;
      if(obj==NULL)  obj = new TObject();
      return obj;
    }
     
    Последнее редактирование модератором: 16 сен 2018
    Mitrandir нравится это.
  5. Mitrandir

    Mitrandir Гуру

    чтобы сделать ее синглтоном и сныкать от неконтроллируемого использования.

    MyLib.h
    Код (C++):

      struct Foo{
         uint8_t a;
         uint8_t b;
         uint8_t c;
       };

    #ifndef API_DISABLED
      #define getFoo _getFoo()
      #define setFooA(_a) getFoo->a = (_a);
      #define setFooB(_b) getFoo->b = (_b);
      #define setFooC(_c) getFoo->c = (_c);
      #define doSomeAction(param)  _doSomeAction(param) ;
    #else
      #define getFoo () (Foo*)NULL;
      #define setFooA(_a)
      #define setFooB(_b)
      #define setFooC(_c)
      #define doSomeAction(param)
    #endif
     

    MyLib.cpp

    Код (C++):

    #include <Arduino.h>
    #include "MyLib.h"

    Foo* _getFoo(){
    static Foo foo;
    if(foo.a!=1){
        foo.a=1;
        foo.b=1;
        foo.c=3;
    }
    return&foo;
    }
    void doSomeAction(char* param){
      Serial.print(param);
      Serial.println(_getFoo()->a++);
    }

     
    mySketch.ino

    Код (C++):

    #include "MyLib.h"

    void setup()
    {
       Serial.begin(9600);
       setFooA(10);
       setFooB(12);
       setFooC(40);
    }

    void loop()
    {
      // some code
       _doSomeAction("Step1");
    //some code
       _doSomeAction("Step2");
    //....
    }


     

    Если первой строкой скетча написать #define API_DISABLED
    то использование библиотеки выпилится из прошивки компилятором
     
  6. qwone

    qwone Гик

    Это как надо ненавидеть классы(структуру как класс), что бы писать им замену.
     
  7. DIYMan

    DIYMan Guest

    Деда, это - НЕ синглтон. Потому как ничто мне не помешает сделать где-то в коде
    Код (C++):
    TObject* some = new TObject();
    Синглтон - гарантирует единственность экземпляра. И делается через приватный конструктор и статический метод-член.
     
    DetSimen нравится это.
  8. DIYMan

    DIYMan Guest

    Это - НЕ синглтон.
     
  9. Не надо усложнять и придумывать какие-то гарантии и прочую чушь. При корректном использовании это работает как синлтон. А если кто-то захочет его сломать, то как ни пыжься — он это сделает. Хотя бы обратившись к конструктору прямо по адресу.
     
  10. DIYMan

    DIYMan Guest

    Это не чушь, а определение синглтона. Усложнение тут не при чём - приведённый выше подход имеет место быть и право на жизнь, просто не надо называть это синглтоном, вот и всё.
     
  11. Спасибо за самое правильное определение, самый умный человек. Что бы человечество делало без вас? Все друг друга поняли и разошлись? Так нельзя. Никто же не стал потрясающе умнее и лучше во всех отношениях благодаря вашему неприкасаемому единственно верному определению синглтона.
     
  12. DIYMan

    DIYMan Guest

    Толсто.
     
  13. DetSimen

    DetSimen Guest

    Да, я согласен, запамятовал. Спасибо, что повозил. :)
     
  14. DIYMan

    DIYMan Guest

    Та не, я без претензий - всякий подход имеет право на жисть ;)
     
  15. DetSimen

    DetSimen Guest

    Так и я без претензий. :) Я не боюсь признавать, что неправ, а та хрень, что я написал в 5 утра по нашему, действительно синглтоном не является. ПризнаЮ.
    С++ пока для меня как польский после русского, вроде чтото понятно, а сиравно плаваю.:)
     
    DIYMan нравится это.
  16. DIYMan

    DIYMan Guest

    Тады слушай, позанудствую, пока дядя Витя недремлющее око отвернул в другую сторону: синглтон к С++ не имеет никакого отношения - это просто паттерн проектирования, реализуется на любом языке, даже челочечьем. Это, строго говоря, инструмент, со своими характерными для инструмента признаками. В рамках профессии, считаю, должна быть определённая грамотность; для меня программирование - профессия, вот и заметил, без всяких претензий и прочего. Занудство окончено ;)

    З.Ы. Сейчас придёт дядя Витя и скажет, что похер как микроскоп называть - всё равно все всё поняли и им можно гвозди забивать :D:D:D
     
    DetSimen нравится это.
  17. DetSimen

    DetSimen Guest

    Спасиба. :):)
     
  18. Всё было сказано правильно.