【问题标题】:Is it possible to pass an iterator from a vector of pointers by reference to another function?是否可以通过引用另一个函数从指针向量传递迭代器?
【发布时间】:2018-09-17 22:26:39
【问题描述】:

我正在开发一个旨在动态模拟道路网络的基本程序。到目前为止,该项目使用父车辆指针类型的向量来存储车辆子对象(汽车、货车、卡车等)。

该项目的目的是计算并求和存储在父向量中的每个车辆子对象所行驶的距离,然后根据行驶的最远距离到最短行驶距离对向量进行重新排序。

我正在使用一种排序算法来比较数据成员total_dist,该数据成员存储每个对象行进的总距离。

由于较早的问题,我必须将向量中每个对象的 total_dist 数据成员显式初始化为 0。

因此,排序算法只“看到”初始化值(即 0),这意味着向量没有被重新排列。

对此的自然解决方案(至少在像我这样的新手程序员的脑海中)是更改计算total_dist 的函数以接受引用传递,以便在程序运行时更新数据成员。

但是,我实际上不确定这在语法上是否可行。这就是我目前所拥有的(我知道我的代码可能真的很丑陋和不优雅,但总的来说我对编程还是很陌生)。

方法

    void Vehicle::set_total_dist(float &f) {
    total_dist += f;           //total_dist is public Vehicle data member
    }

我知道将数据成员设置为公开是不可取的,但这是让我的算法在我目前的能力范围内工作的唯一方法。

向量初始化

    vector<Vehicle*> vehicle_lanes; // 'Vehicle' is the parent class        

    // Populating vector with respective child vehicle objects
    vehicle_lanes.push_back(new Car);       
    vehicle_lanes.push_back(new Van);
    vehicle_lanes.push_back(new Bus);
    vehicle_lanes.push_back(new Lorry);
    vehicle_lanes.push_back(new Motorbike);

    // Setting child object names for identification
    vehicle_lanes[0]->set_name("Car");
    vehicle_lanes[1]->set_name("Van");      
    vehicle_lanes[2]->set_name("Bus");
    vehicle_lanes[3]->set_name("Lorry");
    vehicle_lanes[4]->set_name("Motorbike");

    // Initialising total distance travelled by each object to 0 meters
    vehicle_lanes[0]->total_dist = 0;       
    vehicle_lanes[1]->total_dist = 0;       
    vehicle_lanes[2]->total_dist = 0;
    vehicle_lanes[3]->total_dist = 0;
    vehicle_lanes[4]->total_dist = 0;

如果total_dist 未显式初始化,则未定义初始总和值,因此set_total_dist() 计算我认为是某种字母数字错误值。

向量迭代器和排序算法

    for (vector<Vehicle*>::iterator it = vehicle_lanes.begin(); it != 
    vehicle_lanes.end(); it++) {
        
        // Vehicle sort function
        sort(vehicle_lanes.begin(), vehicle_lanes.end(), 
        CompareVehicleLocation);

        // This is the problem// 
        (*it)->set_total_dist((*it)->get_grid_location());

        // Printing the object name and it's associated Total_dist
        cout << (*it)->get_name() << "'s total distance travelled is: " << 
        (*it)->get_total_dist() << " units." << endl;
    }

当我通过引用传递(*it)-&gt;get_grid_location() 时编译器不喜欢,但是当我通过值传递参数时编译得很好。尝试传递引用时,IDE 在左双括号 (( 之间显示红色下划线。

我在编译之前遇到的错误,当试图通过引用传递时:

非常量引用的初始值必须是左值

编译后得到:

错误 C2664 'void Vehicle::set_total_dist(float &)': 无法转换 参数 1 从 'float' 到 'float &'

我尝试搜索与我相同的帖子,但我没有任何运气,我发现的问题与我的有些相关,例如What's wrong with passing C++ iterator by reference? .由于我缺乏经验,对我来说没有多大意义。

任何建议将不胜感激。我很乐意提供任何其他相关信息。谢谢。

【问题讨论】:

  • 引用传递没有意义,不要在函数中修改。
  • 至于错误,我猜测 get_grid_location() 返回一个float 按值?
  • @HolyBlackCat 我的理解是,通过引用传递确实会在函数中永久修改它。这就是我的目标。如果我目前的方法没有意义,您是否可以提出任何替代方案?
  • @Someprogrammerdude 是的,没错
  • 是的,如果您修改了f,则需要参考。但你没有。

标签: c++ algorithm sorting inheritance vector


【解决方案1】:

快速回答:左值是可以修改的。占用一定内存的东西。右值是暂时的,例如瞬时数、函数的正常返回值等

您的错误cannot convert from 'float' to 'float &amp;' 是将右值float 传递给采用左值引用(float&amp;) 的函数。这意味着您的函数可能会更改它所采用的参数。但是右值没有地址,因此不能更改。这就是编译器拒绝您的代码的原因。

另一个问题是代码中的排序函数应该在 for 循环之外。

【讨论】:

    【解决方案2】:

    我在您的程序中发现了几个问题:

    1) 需要进行一些简化。如果vehicle name与构造函数集成,则无需设置。

    2) total_distance 成员变量可以在类定义本身中初始化为零。

    3)您试图在为每辆车设置total_distance 之前对车辆进行分类。

    4) 使用 auto 关键字替换长类型名称。

    试试这个(我使用的是虚拟距离生成器,因为您的网格逻辑不太清楚):

    #include <iostream>
    #include <vector>
    #include <algorithm>
    
    
    using namespace std;
    
    
    class Vehicle
    {
    protected:
        string name;
        int total_dist{0};   // distance will be set to 0 on any new vehicle
    public:
        Vehicle() {}
        ~Vehicle() {}
        virtual string get_name() = 0;
        int get_total_dist() const { return total_dist; }
        void set_grid_location(int d) {total_dist = d;}
    };
    
    class Car :public Vehicle 
    {
    public:
        Car() 
        {
            name = "Car";  //name will be automatically set
        }
    
        string get_name() { return name; }
    };
    
    class Bus :public Vehicle
    {
    public:
        Bus()
        {
            name = "Bus";
        }
    
        string get_name() { return name; }
    };
    
    int location_generator() // testing only - use your own method
    {
        int arr[] = {4,2,1,5,6,2,3 };
        static int count = 0;
    
        return arr[count++ % 6];
    }
    
    int main()
    {
        vector<Vehicle*> vehicle_lanes;       
    
        //create some vehicles
        vehicle_lanes.push_back(new Car);
        vehicle_lanes.push_back(new Bus);
    
        //filling the location of vehicles before sorting
        for (auto& it = vehicle_lanes.begin(); it != vehicle_lanes.end(); it++)  
        {
            (*it)->set_grid_location(location_generator());
        }
    
        //sorting
        auto CompareVehicleLocation = [](const Vehicle* lhs, const Vehicle* rhs)->bool { return lhs->get_total_dist() < rhs->get_total_dist(); };
    
        sort(vehicle_lanes.begin(), vehicle_lanes.end(), CompareVehicleLocation);
    
    
        //printing sorted vector
        for (auto& it = vehicle_lanes.begin(); it != vehicle_lanes.end(); it++)
        {
            cout << (*it)->get_name().c_str() << "'s total distance travelled is: " <<
                (*it)->get_total_dist() << " units." << endl;
        }
    
        //delete the pointers to avoid memory leak at the end
        for (auto& it = vehicle_lanes.begin(); it != vehicle_lanes.end(); it++)
        {
           delete (*it);
        }
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2020-07-12
      • 2021-11-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-09-15
      • 2019-09-16
      • 2017-03-28
      相关资源
      最近更新 更多