我认为我遗漏了一些关于指针的基本内容。我有以下代码:
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
正确返回,然后看起来该地址的所有内容都变为垃圾,并且在第一个引用之后返回的数据(即data->temperature
等)是不正确。
我可以通过执行以下操作来解决此问题
alicat_data data_ = *data;
但不愿意这样做。我做错了什么是创造我所看到的问题?
答案 0 :(得分:1)
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);
}
}
更新:点击此链接查看指针理论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;
}
升级Apirl 13 :
我正在查看你的classe 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;
}
我注意到您正在返回一个局部变量ac_data = &addr_data;
的地址,该地址变量将在方法Data *alicat::get_data()
完成后删除。这就是你在调用getData
后得到的数据混乱的原因。
要修复它,必须避免返回局部变量,因为它们会在程序退出上下文后被销毁。返回先前使用运算符new
保留的实例。在物体被摧毁的那一刻,你就会有你描述的症状。
我注意到方法alicat_data alicat::parse_data(const std::string &msg)
中存在同样的问题。
更新:考虑到这一点:
我不确定你为什么会得到那个行为,但是我知道在ac_data
的上下文结束但是你分配给{{1的内存'后,局部变量getData
被删除了仍然存在,当你返回该局部变量的地址时,parse_data
释放了它的内存(分配到堆栈而不是堆中的存储块)和这可能是你看到垃圾的原因,但当你使用return (Data*) ac_data;
时,你正在拯救分配到alicat_data data_ = *data;
的内存块......怎么样?这是一个很好的问题,它可以依赖于compilar,但是你可以证明它是调试的方式,并且要小心你要进入的每个内存地址:
parse_data
parse_data
的指针。 getData
的局部变量alicat_data
addr_data
的内存地址。本地指针的地址
从getData
返回的变量alicat_data addr_data
。getData
后,比较指针的地址
getData
vs你进入的指针的地址
alicat_data *data
并比较地址。