【问题标题】:c++ / Elements in a map disapear mysteriously by exiting of a functionc ++ /地图中的元素通过退出函数神秘地消失
【发布时间】:2026-01-03 07:25:01
【问题描述】:

我的代码中有地图问题,我会尽力解释它。

我的代码:(我简化了代码,只保留导致问题的部分)

[prog.cpp]


#include <vector>
#include <iostream>
#include <memory>
#include <fstream>

//this hpp files includes all my other hpp files, i checked the dependencies, all is ok with this
#include "dolmen.hpp"

int main(int argc, char const *argv[]) {
  //creating a dolmen element
  dolmen::Dolmen DolMen;

  //reading the datas
  std::ifstream trame("trame.txt");
  std::ofstream ofs{"report.csv"};
  std::string dataTxt;

  //std::map<int, dolmen::Sensor*> sensorList = dolmen::initialise();
  //std::map<int, dolmen::Sensor*> sensorList = std::map<int, dolmen::Sensor*>();


  //creating a factory element
  /*using AFactory = dolmen::FactorySensor<std::string, std::unique_ptr<dolmen::Sensor>, int, std::string>;
  AFactory factory;*/

  //creating a map to store all the sensors
  std::map<int, std::unique_ptr<dolmen::Sensor>> sensorList;
  //std::map<int, dolmen::Sensor*> sensorList = std::map<int, dolmen::Sensor*>();
  dolmen::initialise(sensorList);

  //i'm gonna simplify the call of the method of my sensor
  [grabbing a sensor in my sensor x list]
  x->getID();
  //my x doesn't exists

[sensorInit.hpp]

#ifndef DOLMEN_SENSOR_INIT_HPP
#define DOLMEN_SENSOR_INIT_HPP 1

/*The DolMen user will only need to modify this file if he needs to add new sensors*/

#include "factorySensor.hpp"
#include "sensor.hpp"
//insert here your sensors hpp files
#include "temperature.hpp"
#include "gyroscope.hpp"
#include "acceleration.hpp"
#include "altitude.hpp"
#include "gps.hpp"
#include "pressure.hpp"

namespace dolmen
{
  //using AFactory = FactorySensor<std::strin    //finding the correct sensor in the sensor list by matching the id with the data frame id
    //dolmen::Sensor* elem;
    std::unique_ptr<dolmen::Sensor> elem;
    if (auto it = sensorList.find(id); it != sensorList.end())
    {
      elem = it->second;
    }

    //searching the maximum number of datas returned by the sensor
    //(some sensors can return one value, some can return many values)
    int max = 0;
    if (elem->getID() == id)
    {
      //decoding the data with the correct sensor, to create a map which contain all the datas of the sensor, from our data frame
      elem->decoding(data);    //finding the correct sensor in the sensor list by matching the id with the data frame id
    //dolmen::Sensor* elem;
    std::unique_ptr<dolmen::Sensor> elem;
    if (auto it = sensorList.find(id); it != sensorList.end())
    {
      elem = it->second;
    }

    //searching the maximum number of datas returned by the sensor
    //(some sensors can return one value, some can return many values)
    int max = 0;
    if (elem->getID() == id)
    {
      //decoding the data with the correct sensor, to create a map which contain all the datas of the sensor, from our data frame
      elem->decoding(data);

      if(abs(int(elem->getValue().size())/elem->getNbAttr()) > max)
      {
        max = int(elem->getValue().size());
      }
    }
    else
    {
      std::cout << "\nsensor not found\n";
    }

      if(abs(int(elem->getValue().size())/elem->getNbAttr()) > max)
      {
        max = int(elem->getValue().size());
      }
    }
    else
    {
      std::cout << "\nsensor not found\n";
    }g, std::unique_ptr<Sensor>, int, std::string>;

  //this file is used to create all the new sensors, the user will only need to modify this one
  inline void initialise(std::map<int, std::unique_ptr<dolmen::Sensor>>& sensorList)
  {
    //creating a factory element
    using AFactory = FactorySensor<std::string, std::unique_ptr<Sensor>, int, std::string>;
    AFactory factory;

    /*//creating a map to store all the sensors
    std::map<int, Sensor*> sensorList = std::map<int, Sensor*>();*/

    //---to change to a for---
    //this is a pointer to a sensor element, used to move the sensors from the factory to our map
    Sensor* sensor = nullptr;

    //the ksp project uses: 00 time / 01 temperature / 02 pressure / 03 acceleration/ 04 gps/ 05 altitude/ 06 gyroscope

    //i only create one sensor for the tests, but i can create many
    //creating a temperature sensor
    factory.registe("temp_sensor", [](int arg1, std::string arg2) { return std::make_unique<Temperature>(arg1,arg2); });
    std::unique_ptr<Sensor> temperature = factory.create("temp_sensor", 01, "temp");
    sensor = temperature.get();
    sensorList.insert(std::make_pair(sensor->getID(), std::move(temperature)));

    //this part works perfectly, i can see all my sensors, call the methods, no problem
    for (const auto &elem: sensorList)
    {
      std::cout << "depuis sensorinit------je suis une id de sensor " << elem.second->getID() << "\n";
      std::cout << "depuis sensorinit------je suis un nom de sensor " << elem.second->getName() << "\n";
    }
  }

} /* dolmen */

#endif

所以问题是:我的传感器存在于我的地图中,只要我在initialise(),但一旦我退出此功能,它们就会突然消失。 我直接在prog.cpp 中尝试了我在initialise() 中的代码,一切都很顺利,所以问题只在我尝试使我的代码离域时出现。

我的理论是:unique_ptr 在退出我的功能时消失了,但我真的不知道是不是这个,如果是这个,我该如何解决这个问题?

祝你有美好的一天

PS:对不起,英语不是我的母语


编辑:现在问题出在其他地方,在一个名为 dolmen.cpp 的文件中,在一个名为解码的方法中(dolmen 是一个类)

dolmen.cpp

std::string Dolmen::decoding(std::string data, std::map<int, std::unique_ptr<dolmen::Sensor>> sensorList)
  {
    //finding the correct sensor in the sensor list by matching the id with the data frame id
    //dolmen::Sensor* elem; --> this is my old version, this worked until my sensor list became to use unique_ptr instead of *
    std::unique_ptr<dolmen::Sensor> elem;
    if (auto it = sensorList.find(id); it != sensorList.end())
    {
      elem = it->second; //the problem is here
    }

    //searching the maximum number of datas returned by the sensor
    //(some sensors can return one value, some can return many values)
    int max = 0;
    if (elem->getID() == id)
    {
      //decoding the data with the correct sensor, to create a map which contain all the datas of the sensor, from our data frame
      elem->decoding(data);

      if(abs(int(elem->getValue().size())/elem->getNbAttr()) > max)
      {
        max = int(elem->getValue().size());
      }
    }
    else
    {
      std::cout << "\nsensor not found\n";
    }
  }

最好的情况如下:我创建了一次sensorList,然后对于要解码的每一行数据,我调用Dolmen::decoding(所以unique_ptr会导致一些问题......)

Hpw 我能解决这个问题吗?

【问题讨论】:

  • 你的理论是正确的。
  • 要么不使用 unique_ptr,要么(可能更好)始终如一地使用它,将您的地图更改为 std::map&lt;int, std::unique_ptr&lt;dolmen::Sensor&gt;&gt;
  • 所以我将拥有:std::map&lt;int, std::unique_ptr&lt;dolmen::Sensor&gt;&gt; 而不是 std::map&lt;int, dolmen::Sensor*&gt;?
  • 我刚刚试了一下...我收到了一条非常混乱的错误消息:/usr/include/c++/9/ext/new_allocator.h:145:20: error: use of deleted function ‘constexpr std::pair&lt;_T1, _T2&gt;::pair(const std::pair&lt;_T1, _T2&gt;&amp;) [with _T1 = const int; _T2 = std::unique_ptr&lt;dolmen::Sensor&gt;]’ 145 | noexcept(noexcept(::new((void *)__p) | ^~~~~~~~~~~~~~~~~~ 146 | _Up(std::forward&lt;_Args&gt;(__args)...))) | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ compilation terminated due to -Wfatal-errors. make: *** [GNUmakefile:209: prog.o] Error 1 (我只粘贴了最后一部分)
  • 没有。我建议编辑您在问题中尝试的内容。然后我说你的初始化应该将它的温度移动到你的 sensorList 中以转移它的所有权。 sensorList.insert(std::make_pair(sensor->getID(), std::move(temperature)));

标签: c++ function class dictionary unique-ptr


【解决方案1】:

您需要将unique_ptrs 保留在地图中,这是您需要执行的操作的简化版本:

#include <iostream>
#include <memory>
#include <map>

void initialise(std::map<int, std::unique_ptr<int>>& map) {
    for(auto i = 0; i < 10; ++i) {
        auto newObject = std::make_unique<int>(i);
        map[i] = std::move(newObject);
    }
}

int main() {
    std::map<int, std::unique_ptr<int>> map;
    initialise(map);

    for(const auto& e : map) {
        std::cout << *(e.second) << std::endl;
    }

    return 0;
}

你可以看到它工作here

【讨论】:

  • 我试过这个,但是这个不能编译了,我也看不懂错误信息
  • 谢谢你的回答,我们决定暂时去掉这个功能,以后有时间再尝试自动化工厂(这是一个学校项目,所以我们没有很多时间)