我仍然在学习现代C++,并决定编写这个虚拟程序,用于实际基准复制语义和移动语义:
#include <chrono>
#include <iostream>
#include <cstdint>
using std::cout;
using std::endl;
class List {
public:
void push_back();
List() : sz{0}, head{nullptr}, tail{nullptr} { }
List(List&& lst) : head{lst.head}, tail{lst.tail}, sz{lst.sz} {
cout << "Move constructor" << endl;
lst.head = nullptr;
lst.tail = nullptr;
lst.sz = 0;
}
List(const List& lst)
{
cout << "Copy constructor" << endl;
for (size_t i = 0; i != lst.sz; ++i)
{
push_back();
}
}
List& operator=(List&& lst)
{
cout << "Move assignment" << endl;
head = lst.head;
tail = lst.tail;
sz = lst.sz;
lst.head = nullptr;
lst.tail = nullptr;
lst.sz = 0;
return *this;
}
List& operator=(const List& lst)
{
cout << "Copy assignment" << endl;
head = nullptr;
tail = nullptr;
sz = 0;
for (size_t i = 0; i != lst.sz; ++i)
{
push_back();
}
return *this;
}
private:
struct ListNode {
ListNode* next;
};
ListNode* head;
ListNode* tail;
size_t sz;
};
void List::push_back()
{
ListNode* new_node = new ListNode;
new_node->next = nullptr;
if (head == nullptr)
{
head = new_node;
}
else
{
tail->next = new_node;
}
tail = new_node;
++sz;
}
class CurrentTime {
std::chrono::high_resolution_clock m_clock;
public:
uint64_t milliseconds()
{
return std::chrono::duration_cast<std::chrono::milliseconds>
(m_clock.now().time_since_epoch()).count();
}
};
List createList(CurrentTime& ct)
{
List lst;
constexpr size_t HUNDRED_MILLION = 100 * 1000 * 1000;
auto start = ct.milliseconds();
for (size_t i = 0; i != HUNDRED_MILLION; ++i)
{
lst.push_back();
}
auto end = ct.milliseconds();
cout << "createList in " << (end - start) << " milliseconds." << endl;
return lst;
}
int main() {
CurrentTime ct;
auto start = ct.milliseconds();
List list;
list = createList(ct);
auto end = ct.milliseconds();
cout << "Duration: " << (end - start) << " milliseconds." << endl;
start = ct.milliseconds();
List list2(list);
end = ct.milliseconds();
cout << "Duration: " << (end - start) << " milliseconds." << endl;
start = ct.milliseconds();
List list3(std::move(list));
end = ct.milliseconds();
cout << "Duration: " << (end - start) << " milliseconds." << endl;
}在这个演示程序中,我成功地捕捉到移动设备的惯用用法吗?告诉我想到的任何事。
发布于 2016-11-06 21:35:50
好的,如果我们要做一些时间,那么让我们修复一些事情。
当我用优化-O3编译它时,它会崩溃。所以要提明斯是很难的。
因此,让我们修复复制构造函数.
根据上下文初始化成员变量。
List a; // Members are default initialized.
List a = List(); // Members are zero initialized.如果成员是默认初始化的,那么POD成员将处于未定义状态。因此,以下构造函数:
List(const List& lst)
{
cout << "Copy constructor" << endl;
for (size_t i = 0; i != lst.sz; ++i)
{
push_back();
}
}当像这样使用时,它的所有成员都没有初始化(因此处于未定义的状态):
List list2(list);因此,调用th push_back()将开始操作一些未定义的指针。
通过显式初始化构造函数中的所有成员或链接将为您完成此操作的构造函数来修复。将默认构造函数初始化为正确的成员,我将将其链接起来。
List(const List& lst)
: List()
{
cout << "Copy constructor" << endl;
for (size_t i = 0; i != lst.sz; ++i)
{
push_back();
}
}IO操作非常复杂,使用IO会发生很大变化。您希望避免在任何计时阶段进行所有IO操作,并在生成所有定时信息之后将结果打印出来。
您应该遵循以下几个标准习惯用法(因为大多数代码都是这样编写的)。
五条规则。你忘了一个破坏者。虽然它不会影响您的timmings,您可能应该写一个只是为了保持整洁。
复制并交换。复制赋值操作符通常是以复制和交换的方式编写的。
交换行动。移动通常作为交换操作来实现。这样,如果不需要的话,您就不必在此时显式地整理内容。但是,如果需要的话,移出的物体最终会进行清理。目前,您的移动分配将泄漏,如果使用。
除:移动操作符应标记为否除。这允许容器内使用它们来执行某些操作,否则将不允许这些操作来维护强异常保证。
class List {
public:
void push_back();
void swap(List& other) noexcept
{
using std::swap;
swap(sz, other.sz);
swap(head, other.head);
swap(tail, other.tail);
}
List()
: head{nullptr}
, tail{nullptr}
, sz{0}
{}
// Copy
List(List const& lst)
: List()
{
for (size_t i = 0; i != lst.sz; ++i)
{
push_back();
}
}
List& operator=(List const& lst)
{
List tmp(lst);
swap(tmp);
return *this;
}
// Move
List(List&& lst) noexcept
: List()
{
swap(lst);
}
List& operator=(List&& lst)
{
swap(lst);
return *this;
}
// Destroy
~List()
{
ListNode* next;
for(auto tmp = head; tmp; tmp = next)
{
next = tmp->next;
delete tmp;
}
}
private:
struct ListNode {
ListNode* next;
};
ListNode* head;
ListNode* tail;
size_t sz;
};
void List::push_back()
{
ListNode* new_node = new ListNode{nullptr};
if (head == nullptr)
{
head = new_node;
}
else
{
tail->next = new_node;
}
tail = new_node;
++sz;
}
class CurrentTime {
std::chrono::high_resolution_clock m_clock;
public:
uint64_t milliseconds()
{
return std::chrono::duration_cast<std::chrono::milliseconds>
(m_clock.now().time_since_epoch()).count();
}
};
List createList(CurrentTime& ct)
{
List lst;
constexpr size_t HUNDRED_MILLION = 100 * 1000 * 1000;
for (size_t i = 0; i != HUNDRED_MILLION; ++i)
{
lst.push_back();
}
return lst;
}
int main() {
CurrentTime ct;
auto start = ct.milliseconds();
List list = createList(ct);
auto end = ct.milliseconds();
cout << "Created Duration: " << (end - start) << " milliseconds." << endl;
start = ct.milliseconds();
List list2(list);
end = ct.milliseconds();
cout << "Copy Duration: " << (end - start) << " milliseconds." << endl;
start = ct.milliseconds();
List list3(std::move(list));
end = ct.milliseconds();
cout << "Move Duration: " << (end - start) << " milliseconds." << endl;
start = ct.milliseconds();
list = list2;
end = ct.milliseconds();
cout << "Copy Assignment: " << (end - start) << " milliseconds." << endl;
start = ct.milliseconds();
list = std::move(list3);
end = ct.milliseconds();
cout << "Move Assignment: " << (end - start) << " milliseconds." << endl;
}注意:你测量移动作业的尝试是错误的。您正在测量创建列表所需的时间,然后移动它。所以我去掉了输出。
https://codereview.stackexchange.com/questions/146317
复制相似问题