首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >基准测试副本语义与移动语义

基准测试副本语义与移动语义
EN

Code Review用户
提问于 2016-11-06 16:43:05
回答 1查看 257关注 0票数 2

我仍然在学习现代C++,并决定编写这个虚拟程序,用于实际基准复制语义和移动语义:

代码语言:javascript
复制
#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;
}

在这个演示程序中,我成功地捕捉到移动设备的惯用用法吗?告诉我想到的任何事。

EN

回答 1

Code Review用户

回答已采纳

发布于 2016-11-06 21:35:50

好的,如果我们要做一些时间,那么让我们修复一些事情。

当我用优化-O3编译它时,它会崩溃。所以要提明斯是很难的。

因此,让我们修复复制构造函数.

.

根据上下文初始化成员变量。

代码语言:javascript
复制
List a;          // Members are default initialized.
List a = List(); // Members are zero    initialized.

如果成员是默认初始化的,那么POD成员将处于未定义状态。因此,以下构造函数:

代码语言:javascript
复制
    List(const List& lst)
    {
        cout << "Copy constructor" << endl;
        for (size_t i = 0; i != lst.sz; ++i)
        {
            push_back();
        }
    }

当像这样使用时,它的所有成员都没有初始化(因此处于未定义的状态):

代码语言:javascript
复制
List list2(list);

因此,调用th push_back()将开始操作一些未定义的指针。

通过显式初始化构造函数中的所有成员或链接将为您完成此操作的构造函数来修复。将默认构造函数初始化为正确的成员,我将将其链接起来。

代码语言:javascript
复制
    List(const List& lst)
        : List()
    {
        cout << "Copy constructor" << endl;
        for (size_t i = 0; i != lst.sz; ++i)
        {
            push_back();
        }
    }

IO和定时工作不太好。

IO操作非常复杂,使用IO会发生很大变化。您希望避免在任何计时阶段进行所有IO操作,并在生成所有定时信息之后将结果打印出来。

标准成语

您应该遵循以下几个标准习惯用法(因为大多数代码都是这样编写的)。

五条规则。你忘了一个破坏者。虽然它不会影响您的timmings,您可能应该写一个只是为了保持整洁。

复制并交换。复制赋值操作符通常是以复制和交换的方式编写的。

交换行动。移动通常作为交换操作来实现。这样,如果不需要的话,您就不必在此时显式地整理内容。但是,如果需要的话,移出的物体最终会进行清理。目前,您的移动分配将泄漏,如果使用。

除:移动操作符应标记为否除。这允许容器内使用它们来执行某些操作,否则将不允许这些操作来维护强异常保证。

代码语言:javascript
复制
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;

}

注意:你测量移动作业的尝试是错误的。您正在测量创建列表所需的时间,然后移动它。所以我去掉了输出。

票数 3
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/146317

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档