【问题标题】:C++ appending to vector of strings efficiently (and idiomatically)C++ 有效地(和惯用地)附加到字符串向量
【发布时间】:2021-05-12 01:37:35
【问题描述】:

如果我想用 C++ 文件中的行填充字符串向量,将push_backstd::move 一起使用是个好主意吗?

{
    std::ifstream file("E:\\Temp\\test.txt");
    std::vector<std::string> strings;
    
    // read
    while (!file.eof())
    {
        std::string s;
        std::getline(file, s);
        strings.push_back(std::move(s));
    }

    // dump to cout
    for (const auto &s : strings)
        std::cout << s << std::endl;
}

或者还有其他一些变体,我可以简单地将一个新的字符串实例附加到向量并获取它的引用?

例如我可以的

std::vector<std::string> strings;
strings.push_back("");
string &s = strings.back();

但我觉得必须有更好的方法,例如

// this doesn't exist
std::vector<std::string> strings;
string & s = strings.create_and_push_back();

// s is now a reference to the last item in the vector, 
// no copying needed

【问题讨论】:

  • 附带说明,您对while (!file.eof()) 的使用是wrong
  • strings.push_back(std::move(s)); 是一个相当便宜的操作。您的另一种方法——首先使用push_back(),然后使用back() 进行输入——也很便宜。但是,有一点你没有考虑到:你应该处理输入失败的情况。在您的第一种方法中,您可以简单地退出。 (顺便说一句,这将使!file.eof() 过时。)在第二种方法中,不要忘记弹出您已经推送用于存储输入的(现在已过时的)空字符串(在您退出之前)。
  • 难道emplace_back() 不会做你想做的事吗(假设 C++17)?

标签: c++ vector reference


【解决方案1】:

除了eof 的误用,这几乎是惯用的做法,是的。 下面是正确的代码:

std::string s;
while(std::getline(file, s))
{
    strings.push_back(std::move(s));
    s.clear();
}

注意显式的s.clear() 调用:对于已移动对象std::string,唯一的保证是您可以在没有先决条件的情况下调用成员函数,因此清除字符串应将其重置为“新鲜”状态,因为不能保证移动对对象做任何事情,你不能依赖getline 不做任何奇怪的事情。

还有其他一些方法可以说明这一点(您可能可以使用istream_iterator 和适当的空白设置来实现类似的效果),但我认为这是最清楚的。

【讨论】:

  • 您的答案中值得一提的一个主要区别是字符串对象在循环之外并被重用,而不是在每次循环迭代时被创建和销毁。
猜你喜欢
  • 2013-03-26
  • 2018-08-20
  • 1970-01-01
  • 2019-12-05
  • 1970-01-01
  • 2013-05-08
  • 1970-01-01
  • 1970-01-01
  • 2016-04-11
相关资源
最近更新 更多