访问指向结构更改值的指针的属性

Accessing properties of pointer to struct changing values

我认为我缺少关于指针的一些基本知识。我有以下代码:

alicat_data *data = (alicat_data*)ent.second->get_data();

if(ent.first == "AlicatA"){

    ui->ac0_P->setValue(data->pressure);
    ui->ac0_T->setValue(data->temperature);
    ui->ac0_Q->setValue(data->flow_rate);
    ui->ac0_Q0->setValue(data->mass_flow_rate);
    ui->ac0_Qsp->setValue(data->setpoint);
 }

它引用了一个定义如下的结构:

struct alicat_data : Data {

    float pressure; /** Pressure in mb */
    float temperature; /** Temperature in degC */
    float flow_rate; /** Volumetric low rate; units are defined by the model */
    float mass_flow_rate; /** Mass flow rate; units are defined by the model */
    float setpoint; /** Device setpoint (if it is a controller); units are defined by the model */
    gas gas_; /** Enum as defined above representing the gas */

    alicat_data(float p = 0, float T = 0, float Q = 0,
            float Q0 = 0, float sp = 0, gas g = Air):pressure(p),
        temperature(T), flow_rate(Q), mass_flow_rate(Q0),
        setpoint(sp), gas_(g){
        setTime();
    }


    virtual std::string serialize2ascii(){return std::to_string(pressure)
            + "\t" + std::to_string(temperature)
            + "\t" + std::to_string(flow_rate) + "\t" + std::to_string(mass_flow_rate)
            + "\t" + std::to_string(setpoint);}

};

当最上面的代码被执行时,第一个引用 data->pressure returns 正确然后看起来该地址上的所有内容都变成垃圾并且数据在第一个引用之后返回(即 data->temperature, 等) 不正确。

我可以通过执行以下操作来解决此问题

alicat_data data_ = *data;

但不想这样做。我做错了什么造成了我所看到的问题?

  • 使用 get_data(),您将获得指向 alicat_data 内存块的指针,它存储在变量 alicat_data *data 中,这是一个指针。
  • 使用 alicat_data data_ = *data; 您将获得实例的内存块,因此您可以使用点“.”访问其方法和属性。

您可以删除变量 alicat_data data_ = *data; 并使用变量 alicat_data *data,如下所示:

    for (auto const &ent : alicat_map){

        alicat_data *data = (alicat_data*)ent.second->get_data();

        if(ent.first == "AlicatA"){

            ui->ac0_P->setValue(data->pressure);
            ui->ac0_T->setValue(data->temperature);
            ui->ac0_Q->setValue(data->flow_rate);
            ui->ac0_Q0->setValue(data->mass_flow_rate);
            ui->ac0_Qsp->setValue(data->setpoint);
        }
    }

更新:检查此link以复习指针理论http://www.cplusplus.com/doc/tutorial/pointers/

我还和你们中的一些人一起制作了一个程序,向你们展示两种方法,你们的和我的:

#include <iostream>
#include <map>

using namespace std;

struct alicat_data {

    float pressure; /** Pressure in mb */
    float temperature; /** Temperature in degC */
    float flow_rate; /** Volumetric low rate; units are defined by the model */
    float mass_flow_rate; /** Mass flow rate; units are defined by the model */
    float setpoint; /** Device setpoint (if it is a controller); units are defined by the model */

    alicat_data(float p = 0, float T = 0, float Q = 0,
        float Q0 = 0, float sp = 0) {

        pressure = p;
        temperature = T;
        flow_rate = Q;
        mass_flow_rate = Q0;
        setpoint = sp;
    }


    virtual std::string serialize2ascii() {
        return "dummy";
    }

};



int main()
{

    map<string, alicat_data *> alicat_map;

    map<string, alicat_data *>::iterator entM;


    alicat_map["AlicatA"] = new alicat_data(1.1,2.2,3.3,4.4,5.5);
    alicat_map["AlicatB"] = new alicat_data(12.1, 23.2, 34.3, 45.4, 56.5);

    //Your Way
    for (auto const &ent : alicat_map) {

        alicat_data *data = (alicat_data*)ent.second; //Get the alicat_data* (pointer) element


        if (ent.first == "AlicatA") {

            alicat_data data_ = *data;

            float pressure = data_.pressure;
            float temp = data_.temperature;
            float rate = data_.flow_rate;
            float mflowrate = data_.mass_flow_rate;
            float setpoint = data_.setpoint;
        }
    }

    //My Way
    for (entM = alicat_map.begin(); entM != alicat_map.end(); entM++)
    {
        alicat_data *data = entM->second; //Get the alicat_data* (pointer) element

        if (entM->first == "AlicatA") {

            float pressure = data->pressure;
            float temp = data->temperature;
            float rate = data->flow_rate;
            float mflowrate = data->mass_flow_rate;
            float setpoint = data->setpoint;
        }
    }

    return 0;
}

4月13日升级:

我正在检查你班级的代码 alicat 我发现了它:

Data *alicat::get_data(){

    alicat_data* ac_data = new alicat_data(0, 0, 0, 0, 0, Air);

    alicat_data addr_data = parse_data(port->async_rw(string(1, address)));

    ac_data = &addr_data;

    return (Data*) ac_data;

}

我注意到您正在 return 获取局部变量 ac_data = &addr_data; 的地址,该变量将在方法 Data *alicat::get_data() 完成后删除。这就是您在调用 getData 后获得的数据混乱的原因。

要修复它,您必须避免使用 return 局部变量,因为一旦程序离开上下文 ,它们就会被销毁。 Return 先前由运算符 new 保留的实例。在对象被破坏的那一刻,你有你描述的症状。

我注意到您在方法 alicat_data alicat::parse_data(const std::string &msg) 中遇到了同样的问题。

更新:考虑一下:

我不确定你为什么会有这种行为,但我知道局部变量 ac_datagetData 的上下文结束后被删除,但是你分配给 ac_data 的内存=27=] 仍然存在,当您 return 获取该局部变量的地址时,return (Data*) ac_data; 它的内存已释放( 分配到堆栈中的内存块而不是进入堆),这可能是你看到垃圾的原因,但是当你使用alicat_data data_ = *data;时,你正在拯救分配到parse_data中的内存块...怎么办!?这是一个很好的问题,它可能取决于编译器,但你可以证明它的方法是调试并注意你进入的每个内存地址:

  1. 分配到 parse_data
  2. 的内存地址
  3. 地址 从 parse_data` returned 到 getData 的指针。
  4. 设置为局部变量 alicat_data addr_data 的内存地址到 getData。局部指针地址 从 getData.
  5. 中 return 得到的变量 alicat_data addr_data
  6. 一旦你离开getData,比较指针的地址 alicat_data *data vs 你得到的指针地址 parse_data 并比较地址。