【问题标题】:How/What to return in this case?在这种情况下如何/返回什么?
【发布时间】:2011-06-23 08:45:04
【问题描述】:

代码:

vector<DWORD> get_running_proc_list()
{
    DWORD proc_list[1024], size;

    if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
    {
        return 0; // PROBLEM HERE!! 
    }

    vector<DWORD> _procs(proc_list, proc_list + size/sizeof(DWORD));
    return _procs;
}

错误:

cannot convert from 'int' to 'const std::vector<_Ty>'

修复此错误的最佳方法是什么?
有没有比只返回空向量更好的方法?

【问题讨论】:

  • 您可以将vector&lt;&gt; 作为参考参数传递给函数。
  • 有多少人在发布答案之前阅读了这个问题? :D

标签: c++ stl coding-style


【解决方案1】:

嗯,你的函数返回vector,而不是DWORD。你不能只返回一个空向量吗:

return std::vector< DWORD >();

return std::vector< DWORD >( 1, 0 );

如果你真的需要0


编辑

还有另一种选择,如果空向量不是解决方案(以防它是某种有效值并且您需要知道) - 使用异常。您可以创建自己的例外类或使用一些标准类。所以,你可以这样做:

if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
{
   throw MyException( "some message, if you want" );
}

如果您选择此选项,我建议您继承 std::exception

或者,在这种情况下,您可以返回指向std::vector 的指针并返回NULL。但我会推荐这个。但这只是我的意见。

【讨论】:

  • @MachineCharmer, vector::size() 检查0 也等同于检查NULL
【解决方案2】:

抛出异常。这就是他们的目的。毕竟,肯定应该有一个正在运行的进程列表。

而且绝对不能不按价值或其他方式返回。在这种情况下,RVO/NRVO 很简单。我的意思是,在最坏的情况下,你可以交换优化。

【讨论】:

    【解决方案3】:

    编辑: (阅读编辑后的问题)

    替代方案:

    1. 您可以让您的函数返回 void 并通过引用(或通过指针)将向量传递给它,然后将向量填充到函数体中。
    2. 你可以让你的函数返回boost::shared_ptr&lt;vector&lt;DWORD&gt; &gt;(或其他一些smart pointer),在函数体中构造和填充向量(当然在动态内存中),然后返回它的地址或NULL。
    3. 如果上述解决方案不合适,则抛出异常。

    【讨论】:

    • +1:但可能存在空向量与“空”向量不同的情况,在这种情况下,我建议返回一个指针(智能指针,当然)到一个向量,并返回一个空指针
    • @Armen +1 以获得好评。在任何情况下,返回指针或引用而不是对象都更便宜。
    • 返回指针可能会更便宜,但为了做到这一点,您必须new 向量,这可能会更昂贵(特别是如果编译器可以优化返回时的副本)。我建议抛出异常,而不是尝试将异常情况编码为返回值。
    • -1 当然你不应该返回空向量。 EnumProcesses 刚刚失败!
    • @Martinho 特别取决于程序应该做什么。但无论如何,在重新阅读问题的编辑版本后,我也决定更改答案。
    【解决方案4】:
    if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
    {
      vector<DWORD> empty;       
      return empty;  <--- 0 sized vector
    }
    

    您可以返回一个空的vector&lt;&gt;

    附带说明,我不建议返回vector按价值。而是将vector&lt;&gt; 作为参数传递,以确保不会发生不必要的副本。

    void get_running_proc_list(vector<DWORD> &_procs) pass by reference and populate
    {
    ...
    }
    

    【讨论】:

    • 我建议首先编写代码,以便它以最佳方式表达您的意图(以及创建blarg 的函数应该返回blarg,而不是每个非const 参考),并保留此类优化,直到您测量并发现这种特殊情况值得优化。 (FWIW,我真的怀疑,当你弄乱进程时,返回几十个整数的std::vector 会产生明显的不同。即使 - 然后出现带有右值引用和移动语义的 C++11 并呈现你的“优化”完全没用,因为它跳过了复制......)
    • @sbi,OP 最初询问过how/what to return。然后编辑为Is there any better way ?。我的回答是针对最初的问题。此外,OP 既没有提到 c++0x 作为范围,也没有提到 vector 有多大。在这种情况下,将vector 作为函数参数传递将是一个不错的选择。
    • C++11 与否 - 我只会在衡量值得这样做之后才进行这样的优化。请注意,虽然我不喜欢你答案的第二部分,但 并没有否决它,因为我喜欢第一部分。
    【解决方案5】:

    替换

    return 0; // PROBLEM HERE!!  
    

    return vector<DWORD>(); // NO PROBLEM!!  
    

    【讨论】:

      【解决方案6】:

      boost::optional 怎么样?它为普通对象添加了指针语义,并允许设置或不设置它们,而无需动态分配。

      #include <boost/optional.hpp>
      
      typedef boost::optional<std::vector<DWORD>> vec_opt;
      
      vec_opt get_running_proc_list()
      {
          DWORD proc_list[1024], size;
      
          if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
          {
              return 0; 
          }
      
          vector<DWORD> _procs(proc_list, proc_list + size/sizeof(DWORD));
          return _procs;
      }
      

      这就是您需要做的所有事情,只需更改返回类型。在调用站点上:

      vec_opt v = get_running_proc_list();
      if(v){
        // successful and you can now go through the vector, accessing it with *v
        vector<DWORD>& the_v = *v;
        // use the_v ...
      }
      

      【讨论】:

        【解决方案7】:

        您正试图返回两个逻辑上不同的信息位:第一,“进程列表是什么?”第二,“我可以计算进程列表吗?”。我建议您以两个不同的变量返回它们:

        // UNTESTED
        bool get_running_proc_list(vector<DWORD>& result)
        {
          DWORD proc_list[1024], size;
        
          if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
          {
            return false; 
          }
        
          result = vector<DWORD>(proc_list, proc_list + size/sizeof(DWORD));
          return true;
        }
        

        但是,我可能会尝试保存几个 memcpy 的:

        // UNTESTED
        bool get_running_proc_list(vector<DWORD>& result)
        {
          result.clear();
          result.resize(1024);
        
          DWORD size;
          if(!EnumProcesses(&result[0], result.size()*sizeof(DWORD), &size))
          {
            result.clear();
            return false; 
          }
          result.resize(size/sizeof(DWORD));
        
          return true;
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2016-03-02
          • 2014-09-12
          • 2018-04-26
          • 2018-05-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多