【问题标题】:c++ vector of pointers to vector of pointers orderingc++ 指针向量到指针向量
【发布时间】:2020-04-13 17:07:27
【问题描述】:

我有两个类,每个类都有一个指向Data 的指针向量。我想要做的是将Sample2类的向量中的指针分配给Sample1类的向量中的指针。 问题是当我在第二个向量中分配指针时,它们存储的顺序是第一个向量的顺序。我想按插入顺序存储它们。

这是minimal reproducible example的代码:

#include <iostream>
#include <vector>

using namespace std; //for sample purposes

// For simplicity, the data is just a string in this example.
using Data = string;
// In the real code there is a class with a certain vector as a member,
// but for this example we can reduce it to just the vector.
using Sample1 = vector<Data*>;

Class Sample2——问题就在这里

class Sample2 {
    vector<Data*> autodromos2;

public:
    vector<Data*>& getAutodromos() { return autodromos2; }

    // ** This is the function with the problem. **
    void addAutodromos2(vector<string>& arguments, vector<Data*>& autodromos)
    {
        for (Data* a : autodromos) {
            for (string &s : arguments) {
                if (s == *a) { // The real test is more complex.
                    getAutodromos().push_back(a);
                    break;
                }
            }
        }
    }
};

主函数(生成数据并调用addAutodromos2

int main()
{
    // Create the list of elements to add to a `Sample2`.
    // Note that these are strings, not Data objects (in the real code).
    vector<string> arguments { "fourth", "first", "third" };

    // Create the `Sample1` data with which to work.
    Sample1 s1 {
        new Data("first"), new Data("second"), new Data("third"), 
        new Data("fourth"), new Data("fifth") 
    };

    // Create the `Sample2` data from the list and `s1`.
    Sample2 s2;
    s2.addAutodromos2(arguments, s1);

    // Diagnostic:
    for (Data* a : s2.getAutodromos()) {
        cout << *a << endl;
    }
}

输出是

first 
third 
fourth

应该是什么时候

fourth 
first 
third

【问题讨论】:

    标签: c++ sorting pointers stdvector


    【解决方案1】:

    其实addAutodromos2()中循环的顺序问题你需要用下面的代码改变函数:

        for (string s : arguments) 
        {
            for (Data* a : autodromos) 
            {            
                if (s == *a) { // The real test is more complex.
                    getAutodromos().push_back(a);
                    break;
                }
            }
        }
    

    切换 for 循环。输出为fourth first third

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:

      有一种观点认为,如果您在函数内部有嵌套循环,那么您可能思考的不够抽象。尽管有时这可能夸大其词,但在这种情况下确实有价值。让我们看看内部循环。

                  for (string s : arguments) {
                      if (s == *a) {
                          getAutodromos().push_back(a);
                          break;
                      }
                  }
      

      此循环在arguments 中搜索*a,如果找到则执行某些操作。搜索是一个可以抽象为自己的函数的概念,我们称之为found,一个返回bool的函数。

          // Preliminary revision
          void addAutodromos2(vector<string>& arguments, vector<Data*>& autodromos)
          {
              for (Data* a : autodromos) {
                  if ( found(arguments, *a) ) {
                      getAutodromos().push_back(a);
                  }
              }
          }
      

      只看一个循环,应该更清楚问题是什么。元素按照它们在autodromos 中出现的顺序添加到getAutodromos()。要使用arguments 中的订单,您需要循环访问它。 (我会将辅助函数的名称更改为 find_by_name 并让它返回找到的元素的迭代器或结束迭代器。布尔返回值不再足够。)

          // Final revision
          void addAutodromos2(vector<string>& arguments, vector<Data*>& autodromos)
          {
              for (string s : arguments) {
                  auto result = find_by_name(autodromos, s);
                  if ( result != autodromos.end() ) {
                      getAutodromos().push_back(*result);
                  }
              }
          }
      

      这里缺少的部分是find_by_name 函数。好消息是这个任务很常见,that functionality is part of the standard library,在标题&lt;algorithm&gt; 中。坏消息是使用库函数需要进行一些输入,因为参数更复杂(为了更大的灵活性)。您可能需要定义一个包装器来专门针对您的情况。

      // Returns an iterator to the element with the indicated name, or
      // autodromos.end() if not found.
      static auto find_by_name(const vector<Data*> & autodromos, const string & name)
      {
          return std::find_if(autodromos.begin(), autodromos.end(), [&name](Data *a){
              return name == *a; // or name == a->get_name(), when Data is more complex
          });
      }
      

      请注意,如果真正的测试就像比较name == *a 一样简单,那么可以使用std::find 代替std::find_if,并且不需要使用lambda。 不要忘记在文件的前面#include &lt;algorithm&gt;

      【讨论】:

        猜你喜欢
        • 2011-08-04
        • 1970-01-01
        • 2019-09-10
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多