Class methods read different values of the same va

2019-08-26 04:30发布

My class has a variable of a user-defined type. I set this variable in one method of the class. When I try to get this variable from another method of the same class, the value is always 0, although the variable has not been changed anywhere else.

I really don't understand why this happens! Follwoing is a sample of my code:

myclass.h

typedef enum {
    ACTIVE   =  0,  
    SLEEP    =  1,  
    FINISHED =  2,  
    WAITING  =  3,
    KILLED   =  4
} Mode;


class MyClass
{
    public:
      void statusReceive(void);
      Mode getCurrentMode(void);

    private:
      Mode currentMode;
};

myclass.cpp

#include "myclass.h"

void MyClass::statusReceive(void)
{
    currentMode = (Mode)interpretMsg(&msg);
    printf("current Mode = %d\n", this->currentMode); // prints 4
}

Mode MyClass::getCurrentMode(void)
{
    printf("current Mode = %d\n", this->currentMode);   // prints 0
    return this->currentMode;
}

main.cpp

#include "myclass.h"

MyClass myclass;

void timerStart(std::function<void(void)> func, unsigned int interval)
{
    std::thread([func, interval]()
            { 
            while (true)
            { 
            auto x = std::chrono::steady_clock::now() + std::chrono::milliseconds(interval);
            func();
            std::this_thread::sleep_until(x);
            }
            }).detach();
}

int main(void)
{
    timerStart(std::bind(&MyClass::statusReceive, myclass), 10);
    Mode x = myclass.getCurrentMode();
    printf("Current Mode = %d\n", x); // prints 0
}

标签: c++ oop
1条回答
Rolldiameter
2楼-- · 2019-08-26 05:23

I see two problems with this code.

First, std::bind does a copy (or move) of all its arguments. So the functor value returned from bind contains another MyClass object which was copy-constructed from the myclass object, and calls to that functor will only change the internal MyClass, not myclass.

You could use a reference-wrapper to specify using the same MyClass object:

timerStart(std::bind(&MyClass::statusReceive, std::ref(myclass)), 10);

or just switch to a lambda to call the member function on myclass directly:

timerStart([](){ myclass.statusReceive(); }, 10);

Second, you are modifying the myclass.currentMode object in one thread and reading it in another without any synchronization between the two operations. This is a data race and undefined behavior.

查看更多
登录 后发表回答