【问题标题】:returning an array of vectors in C++在 C++ 中返回一个向量数组
【发布时间】:2013-02-23 20:03:13
【问题描述】:

我在返回字符串向量数组时遇到了困难。我有一个功能:

std::vector<std::string>* generatecVec(std::vector<std::string> strVec){
  std::vector<std::string> cVec[3];
  cVec[0].push_back("Test11");
  cVec[0].push_back("Test12");
  cVec[0].push_back("Test13");
  cVec[1].push_back("Test21");
  cVec[1].push_back("Test22");
  cVec[1].push_back("Test23");
  cVec[2].push_back("Test31");
  cVec[2].push_back("Test32");
  cVec[2].push_back("Test33");
  return cVec;
}

后来我使用像

这样的功能
std::vector<std::string> *cVec = generatecVec(strVec);
for(std::vector<string>::iterator it = cVec[0].begin(); it != cVec[0].end(); ++it) {
    std::cout << *it;
}

但我不断收到分段错误。我意识到我必须不正确地使用指针,但我该如何解决这个问题?我使用向量数组是因为它很容易通过索引来引用它(我只需要三个,非动态的)。谢谢!

【问题讨论】:

  • 我看到您没有接受任何问题的答案。 Accept and/or upvote 一个您认为有帮助的答案。

标签: c++ arrays pointers vector


【解决方案1】:

您正在返回一个指向仅存在于函数范围内的东西的指针。函数完成后,cVec 消失,调用者留下一个悬空指针。我建议返回一个可以实际复制的对象,例如std::array&lt;std::vector&lt;std::string&gt; 3&gt;

#include <array> // for std::array

std::array<std::vector<std::string>,3> generatecVec(/*std::vector<std::string> strVec*/){
  std::array<std::vector<std::string>,3> cVec;
  cVec[0].push_back("Test11");
  cVec[0].push_back("Test12");
  cVec[0].push_back("Test13");
  cVec[1].push_back("Test21");
  cVec[1].push_back("Test22");
  cVec[1].push_back("Test23");
  cVec[2].push_back("Test31");
  cVec[2].push_back("Test32");
  cVec[2].push_back("Test33");
  return cVec;
}

我在这里注释掉了strvec,因为它似乎在函数中没有任何作用。

然后您可以像这样使用它(基于 C++11 范围的 for 循环语法):

auto cVec = generatecVec(); // no strVec because it doesn't play any role
for(auto it = cVec[0].cbegin(); it != cVec[0].cend(); ++it) {
    std::cout << *it;
}

请注意,如果您的编译器支持 C++11 初始化程序列表初始化,则可能不需要 push_backs

如果您的编译器不支持std::array,请尝试std::tr1::array from 或boost::array

【讨论】:

    【解决方案2】:

    您正在返回一个指向自动数组的指针,该数组在超出范围时被破坏,并且您的指针指向一个充满破坏向量的破坏数组。

    使用std::array并按值返回:

    // This means: std::array of 3 std::vector<string>
    //   Type--VVVVVVVVVVVVVVVVVVVVVVVV  V-- Array size
    std::array<std::vector<std::string>, 3> generatecVec(std::vector<std::string> strVec){
      return { {
         { "Test11", "Test12", "Test13" },
         { "Test21", "Test22", "Test23" },
         { "Test31", "Test32", "Test33" }
      } };
    }
    
    auto cVec = generatecVec(strVec);
    for(auto it = cVec[0].begin(); it != cVec[0].end(); ++it) {
        std::cout << *it;
    }
    

    【讨论】:

      【解决方案3】:

      奇怪的是,当你需要收集字符串时使用字符串向量,而当你需要收集向量时使用指针。使用 typedef 应该有助于抽象细节并查看可能的解决方案:

      typedef std::vector<std::string> strings;
      typedef std::vector<strings> strings_seq;
      
      strings_seq generateVec()
      {
        strings_seq cVec( 3 );
        cVec[0].push_back("Test11");
        cVec[0].push_back("Test12");
        cVec[0].push_back("Test13");
        cVec[1].push_back("Test21");
        cVec[1].push_back("Test22");
        cVec[1].push_back("Test23");
        cVec[2].push_back("Test31");
        cVec[2].push_back("Test32");
        cVec[2].push_back("Test33");
        return cVec;
      }
      

      【讨论】:

        【解决方案4】:

        正如其他人已经解释的那样,您正在返回一个本地引用,即函数范围之外的垃圾。 根据经验,我会尽量避免使用原始指针,因为最终我会忘记在使用后删除指针,或者忘记初始化要开始的指针。

        当您返回 std::array 或 std::vector 时,您调用复制构造函数并接收向量、数组等的新副本...我个人倾向于在这些情况下使用 boost shared_ptr,因为它们克服了经典 C 指针带来的大多数缺点

        【讨论】:

        • 当您返回 std::array 或其他任何值时,您会语义调用副本,但 C++ 标准允许在此处进行复制省略,特别是返回值优化 (RVO) ,并且大多数当前的编译器都实现了这一点。所以实际上返回shared_ptr 没有什么意义。如果你确实返回了一个智能指针,在这种情况下它应该是一个unique_ptr
        • 这可能是。但不能保证每个编译器都使用这种优化。所以最好写一个干净的代码(可能是shared_ptr或unique_ptr)而不是希望目标环境有这样的优化
        • 我想说干净的代码是按值返回的。编译器更有可能执行 RVO,所以我会把这个论点颠倒过来:如果你有一个不执行 RVO 的编译器,那么你可以想办法。一种选择是获得更现代的编译器!
        猜你喜欢
        • 2014-01-06
        • 2011-01-25
        • 1970-01-01
        • 1970-01-01
        • 2014-08-02
        • 1970-01-01
        • 2016-11-20
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多