C++ 从函数调用的多次返回中构建字符串向量的最佳方法

Posted

技术标签:

【中文标题】C++ 从函数调用的多次返回中构建字符串向量的最佳方法【英文标题】:C++ best way to build vector of strings from multiple returns of function calls 【发布时间】:2013-11-14 08:34:43 【问题描述】:

我正在练习 C++,所以这不是将要投入生产的代码,但我很想知道:

我有一个指向 Player 类型对象的指针向量:

std::vector<Player*> _players;

当我调用它的方法get_name() 时,每个玩家都将他的名字返回给我std::string,例如:

std::string player0_name = _players[0]->get_name();

我想将所有玩家名称传递给一个函数,该函数期望它们作为字符串向量的引用:

void all_player_names( std::vector< std::string >& );

现在我知道通过一些临时变量很容易做到这一点。我可以先创建一个字符串向量,在其中存储所有玩家姓名,然后将其传递给函数all_player_names 作为参考。

但我正在寻找一种无需创建临时变量的方法。它应该类似于 Python 中的列表推导。它必须遍历Player 指针数组,在每个指针上调用get_name() 函数,从返回的字符串中构建一个向量并将其直接传递给函数all_player_names。我假设它应该可以使用 lambda 函数和 STL 中的一些算法,但我不知道是哪一个。

所以它看起来或多或少应该是这样的:

all_player_names(<function that i'm looking for>(
    _players, [](Player* p)  return p->get_name();
);

STL中有这样的算法吗?

【问题讨论】:

从返回的字符串中构建一个向量 ... 一个临时变量,不是一个理解.列表推导更像是一个迭代器对,其中取消引用迭代器会动态生成值 老实说,看看下面的答案,我更喜欢 for 循环。我的意思是,它仍然没有接近var names = players.Select(p =&gt; p.Name) :-) 【参考方案1】:

最简单的方法是使用累积并使用将通过二进制操作传递并返回的临时变量:

std::accumulate(_players.begin(), _players.end(), 
 std::vector<std::string>(),
 [](std::vector<std::string>& vector, const Player* elem) 
   
    vector.push_back(elem->get_name());
    return vector;
   );

感谢移动语义,它在 C++11 中应该几乎没有性能开销。

【讨论】:

如果你打算像你一样调用push_back,你应该使用空构造函数创建向量。 +1 您的解决方案很好。仍然请在答案中指出您仍然创建一个临时变量并将其作为参数传递。这个函数声明无法避免这种情况。【参考方案2】:

在我看来,最好使用标准算法 std::transform 而不是 std::accumulate。在这种情况下,std::transform 的语义比 std::accumulate 的语义更清晰。例如

    struct Player
    
    public:
        Player( const std::string &s ) : s( s ) 
        const std::string & get_name() const
        
            return s;
        
    private:
        std::string s;
    ;

    std::vector<Player *> v1;

    v1.push_back( new Player( "Hello" ) );
    v1.push_back( new Player( "Player" ) );

    std::vector<std::string> v2;
    v2.reserve( v1.size() );


    std::transform( v1.begin(), v1.end(), std::back_inserter( v2 ), 
                    std::mem_fun( &Player::get_name ) );

    for ( const std::string &s : v2 ) std::cout << s << ' ';
    std::cout << std::endl;

【讨论】:

【参考方案3】:

如果你有一个参数是 const ref,你别无选择,只能构造一个变量。你的 const ref 应该指向一些现有的对象。您可以更改您的函数以获取指向函数的指针和指向std::vector&lt;Player*&gt; 的常量引用。让函数获取指向Player 的指针并返回他的名字。

【讨论】:

【参考方案4】:

你想要的是使用 lambda 表达式(或匿名函数)。

现在可以使用 C++11,但不能使用以前的版本。问题也处理here。

在你的情况下,我会在新类 Players 中使用一个方法:

class Players 
public:
    void addPlayer(Player*);
    void removePlayer(Player*);
    vector<string> getNames() 
      std::vector<string> names;
      for(unsigned int i = 0; i != players_.size(); ++i) 
        names.push_back(players_[i]->getName());
      
    return names;
    
private:
vector<Player*> players_;

;

【讨论】:

我不知何故看不到在 c++11 之前不起作用的代码部分。我也不太明白这如何解决 OP 的问题。

以上是关于C++ 从函数调用的多次返回中构建字符串向量的最佳方法的主要内容,如果未能解决你的问题,请参考以下文章

函数中的c ++大向量多次调用

C++ 函数返回一个向量/字符串,但不是一个数组

C ++返回最少许多递归调用的最佳方法

具有最快“存在”搜索的 C++ 容器(向量/数组/等)

从函数 C++ 返回向量

C++ 从函数调用向量到 Main