🔴 同一份数据,三种交法
(本条路线统一用 g++ -std=c++17 -O0 -Wall 编译)⚠️ 这一节的计数**只数标准强制的那几种**(传值、传 const&、push_back 一个左值 / 一个 move 过的),**不数返回值和临时对象**——那些各编译器省略得不一样。所有 vector 都**先 reserve**,扩容搬运不掺进来。
#include <iostream>
#include <string>
#include <vector>
struct Item {
std::string name;
static int copies, moves;
explicit Item(std::string n) : name(std::move(n)) {}
Item(const Item &o) : name(o.name) { copies++; }
Item(Item &&o) noexcept : name(std::move(o.name)) { moves++; }
Item &operator=(const Item &) = default;
Item &operator=(Item &&) = default;
};
int Item::copies = 0;
int Item::moves = 0;
static int len_by_value(Item x) { return static_cast<int>(x.name.size()); }
static int len_by_ref(const Item &x) { return static_cast<int>(x.name.size()); }
int main() {
std::vector<Item> v;
v.reserve(2);
int cap_ok = (v.capacity() >= 2); /* 标准保证 reserve(n) 之后 capacity() >= n */
Item a("apple");
len_by_value(a); /* 传值:拷一次 */
int after_value = Item::copies;
len_by_ref(a); /* 传 const& :一次都不拷 */
int after_ref = Item::copies;
v.push_back(a); /* 左值:再拷一次 */
v.push_back(std::move(a)); /* 明说搬:不拷 */
std::cout << cap_ok << "/" << after_value << "/" << after_ref << "/"
<< Item::copies << "/" << Item::moves << "\n";
return 0;
}
全部评论