C++ 11 rvalue and move:遗留代码可以避免复制吗?

Nul*_*ptr 2 c++ rvalue-reference move-semantics c++11 call-by-value

请理解我还在学习C++ 11的移动和rvalue语义的概念.我的问题是遗留代码是否可以通过简单地使用C++ 11编译器和STL获得避免不必要的副本的免费午餐.

这是一个非常简单的例子.此代码为给定字符串构建一个简单的字符频率表.例如,"apple"应该返回{('a', 1), ('e', 1), ('l', 1), ('p', 2)}.正如您将看到的,我只是使用向量作为值.

typedef std::tuple<char, int> Frequency;
typedef std::vector<Frequency> Frequencies;

Frequencies buildFrequenciesTable(std::string w) {
  char table['z' - 'a' + 1] = { 0, };
  std::for_each(w.cbegin(), w.cend(), [&table](char c) {
    ++table[::tolower(c) - 'a'];
  });

  Frequencies freqs;
  for (size_t i = 0; i < 'z' - 'a' + 1; ++i) {
    if (table[i] != 0)
      freqs.push_back(tuple<char, int>((char) ('a' + i), table[i]));
  }
  return freqs; // Q1: Is vector get copied?
}

int main() {
  using namespace std;

  Frequencies f1 = buildFrequenciesTable("apple"); // Q2: Copy?
  Frequencies f2 = buildFrequenciesTable("banana");
  vector<Frequencies> fs = { f1, f2 }; // Q3: Copy?
}
Run Code Online (Sandbox Code Playgroud)

很明显,当将向量作为值返回时,C++ 03会生成所有复制代码(使用复制构造函数和赋值运算符).在C++ 11中怎么样?std::vectora有移动构造函数.这段代码可以避免任何unnessarry副本吗?或者,我应该使用&&std::forward在上面的代码?

我试图调试内部STL代码,但很难说服.

注意:我的目标是尽量减少这些功能中不必要的副本.我知道我可以使用new/pointers/references,但这需要解决内存泄漏问题.所以,我想尽可能多地使用价值观.

Dan*_*rey 5

对于Q1,即使在C++ 03中也很可能没有副本,因为"命名返回值优化"(NRVO)删除了副本.

对于Q2,即使在C++ 03中也很可能没有副本,因为copy-elision会删除它.

对于Q3,即使在C++ 11中,您可以根据需要进行标记f1f2移动,以便实际移动它们:

vector<Frequencies> fs = { std::move(f1), std::move(f2) };
Run Code Online (Sandbox Code Playgroud)

既然你问过多个问题我想我会省略进一步的解释,查看NRVO,copy-elision以及std::move需要的地方,询问你是否还有其他问题.

但是,在某些情况下,您可以获得自由移动,例如,如果有可移动的临时移动:

vector<Frequencies> fs = { buildFrequenciesTable("apple"),
                           buildFrequenciesTable("bananas") };
Run Code Online (Sandbox Code Playgroud)

以上将检测从buildFrequenciesTable()临时返回的两个向量,因此它们将被移入fs.