在这种情况下应该返回什么?

4

代码:

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<> 作为引用参数传递给函数。 - iammilind
有多少人在发布答案之前阅读了问题? :D - Pratik Deoghare
7个回答

4
好的,您的函数返回的是vector,而不是DWORD。您可以返回一个空的vector
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 - iammilind

3

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

而且一定不要失败地通过值或其他方式返回。在这种情况下,RVO / NRVO 很容易应用。我的意思是,最坏的情况下,你可以进行交换优化。


2

编辑:(在阅读问题的编辑版本后)

替代方案:

  1. 您可以使函数返回void并通过引用(或指针)传递一个向量,然后在函数体中填充该向量。
  2. 您可以使函数返回boost::shared_ptr<vector<DWORD> >(或其他一些智能指针),在函数体中构造和填充向量(当然是在动态内存中),然后返回其地址或NULL。
  3. 如果上述解决方案不适用,则抛出异常。

2
但是有一种情况,空向量并不等同于“null”向量,这种情况下我建议返回指向向量的指针(当然是智能指针),并返回空指针。 - Armen Tsirunyan
@Armen,赞一个好评论。无论如何,返回指针或引用而不是对象更加经济实惠。 - Mihran Hovsepyan
返回指针可能更加经济高效,但为了实现这一点,您必须使用 new 来创建向量,这可能会更加昂贵(特别是如果编译器可以优化返回时的复制)。我建议抛出异常,而不是尝试将异常情况编码为返回值。 - Mike Seymour
-1 当然不应该返回空向量。EnumProcesses 函数执行失败了! - R. Martinho Fernandes
@Martinho 特别取决于程序的功能。但无论如何,在重新阅读问题的编辑版本后,我决定改变回答。 - Mihran Hovsepyan

1
if(!EnumProcesses(proc_list, sizeof(proc_list), &size))
{
  vector<DWORD> empty;       
  return empty;  <--- 0 sized vector
}

你可以返回一个空的vector<>

顺便提一下,我不建议通过值来返回vector。相反,将vector<>作为参数传递,以确保不会发生不必要的复制。

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

2
我建议首先编写代码,以便最优地表达您的意图(创建一个 blarg 的函数应该返回一个 blarg,而不是通过非 const 引用获取一个),并将这样的优化留到您测量并发现这个特定情况值得优化时再进行。(顺便说一句,当您处理进程时,返回几十个整数的 std::vector 不会产生明显的差异。即使有 - 随着 C++11 的出现,右值引用和移动语义使您的“优化”完全无用,因为它跳过了复制...) - sbi
@sbi,OP最初问的是“如何/返回什么”。然后编辑为“有没有更好的方法?”我的答案是针对最初的问题。此外,OP既没有提到“c++0x”作用域,也没有说明“vector”的大小。在这种情况下,将一个“vector”作为函数参数传递是一个不错的选择。 - iammilind
C++11与否 - 只有在测量其值得之后,我才会进行这样的优化。请注意,虽然我不喜欢你回答的第二部分,但我没有对其进行投票,因为我喜欢第一部分。 - sbi

1

替换

return 0; // PROBLEM HERE!!  

使用

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

1

使用 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 ...
}

0

您正试图返回两个逻辑上不同的信息:第一个是“进程列表是什么?”,第二个是“我能计算出进程列表吗?”。我建议您将它们分别存储在两个变量中:

// 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;
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接