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

C++ best way to build vector of strings from multiple returns of function calls

本文关键字:字符串 构建 向量 最佳 方法 返回 函数调用 C++      更新时间:2023-10-16

我正在练习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中有这样的算法吗?

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

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 中几乎没有性能开销。

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

    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;

如果你有一个 const ref 的参数,你别无选择,只能构造一个变量。您的常量引用应指向某个现有对象。您可以将函数更改为将指针指向函数和常量引用更改为std::vector<Player*>。使函数获取指向Player的指针并返回他的名字。

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

现在可以使用 C++11,但以前的版本则不行。这里也处理了问题。

在您的情况下,我会在新类中使用一种方法 玩家:

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_;

};