首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >访问指针的属性以更改值

访问指针的属性以更改值
EN

Stack Overflow用户
提问于 2017-04-12 17:48:34
回答 1查看 54关注 0票数 0

我认为我错过了一些关于指针的基本内容。我有以下代码:

代码语言:javascript
复制
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);
 }

引用定义为以下结构的结构:

代码语言:javascript
复制
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将正确返回,那么该地址上的所有内容都会变成垃圾,并且在这个第一个引用之后返回的数据(即data->temperature等)是不正确的。

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

代码语言:javascript
复制
alicat_data data_ = *data;

但不愿意这么做。我做了什么错事,造成了我所看到的问题?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-04-12 23:25:59

  • 使用get_data(),您将获得指向alicat_data内存块的指针,并将其存储到可变的alicat_data *data中,即指针。
  • 使用alicat_data data_ = *data;,您将获得实例的内存块,因此可以使用点'.‘来访问它的方法和属性。

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

代码语言:javascript
复制
    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);
        }
    }

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

我还和你们中的一些人做了一个节目,向你们展示两种方法,你们的和我的:

代码语言:javascript
复制
#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;
}

Apirl 13的升级

我在检查你的分类alicat的代码时发现了它:

代码语言:javascript
复制
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;

}

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

要修复,您必须避免返回局部变量,因为它们在程序脱离上下文后被销毁,。返回以前由操作符new保留的实例。当物体被摧毁时,你就有了你描述的症状。

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

更新:如下所示:

我不知道为什么会有这种行为,但我知道局部变量ac_data是在getData上下文结束后删除的,但是分配给parse_data的内存仍然存在,当您返回局部变量的地址时,它释放的内存(是分配到堆栈中的内存块,而不是堆),这可能是看到垃圾的原因,但是当使用alicat_data data_ = *data;时,您正在拯救分配给parse_data的内存块.怎么会!?这是一个很好的问题,它可能取决于编译器,但您可以通过何种方式来证明它是调试的,并且要小心您要进入的每个内存地址:

  1. 分配给parse_data的内存地址
  2. getData返回到parse_data`的指针的地址。
  3. 将局部变量alicat_data addr_data设置为getData的内存地址。从alicat_data addr_data返回的局部变量getData的指针地址。
  4. 离开getData后,比较指针alicat_data *data的地址与parse_data中指针的地址,并比较地址。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/43376347

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档