c++ - 为什么复制和 move 构造函数以相同数量的 memcopies 结束?

标签 c++ c++11 copy-constructor move-semantics move-constructor

这里的问题是了解在通过函数的返回对象初始化 vector 时是否调用了复制或 move 构造函数。 使用探查器检查 mallocs 在两种情况下显示相似的 memcopies。为什么?

我们有一个类型为“消息”的类。该类提供了一个函数“data_copy”,它将“消息”的内容作为 vector 返回。

我尝试了 2 个选项。 一种是直接使用复制构造函数来初始化一个新的vector。

std::vector<uint8_t> vector1 ( message.data_copy() );

第二个选择是尽量避免额外的复制并做

std::vector<uint8_t> vector1 ( std::move( message.data_copy() ) );

作为引用,我附上了 data_copy() 的作用。

std::vector<uint8_t> message::data_copy(void) const
{
    std::vector<uint8_t> d(this->size());
    copy_data_to_buffer(d.data());
    return d;
}
void message::copy_data_to_buffer(uint8_t* buffer) const
{
    DEBUG_LOG("copy_data_to_buffer");
    for(const fragment* p = &head; p != nullptr; p = p->next)
    {
        memcpy(buffer, p->data[0], p->size[0]);
        buffer += p->size[0];

        if(p->size[1])
        {
            memcpy(buffer, p->data[1], p->size[1]);
            buffer += p->size[1];
        }
    }
}

最后,通过使用分析器,我比较了 malloc 调用的数量。虽然人们会期望 move 构造函数在现实中避免额外的 memcopy,但它们在两种情况下都是相同的。

最佳答案

您两次都在使用 move 构造函数。 data_copy 的结果是临时的。然后用这个临时参数构造 vector。所以这是一个举动。

第二次,您基本上是将已经是右值引用的对象强制转换为右值引用,因此再次使用了 move 构造函数。两者的行为应该绝对没有区别。

我想,您可能误解了什么是临时对象以及什么是右值引用。您不必经常使用 ::std::move 并且如果您正在使用它,您应该仔细查看您正在使用它的代码以确保您做的是正确的事情.

Godbolt 上的代码是 proof that the copy constructor is never called .这是链接到的代码:

#include <utility>

struct ICantBeCopied {
    ICantBeCopied(ICantBeCopied const &) = delete;
    ICantBeCopied(ICantBeCopied &&) {}
    ICantBeCopied() {}
};

ICantBeCopied make_a_copy()
{
    ICantBeCopied c;
    return c;
}

void a_function()
{
    ICantBeCopied a{make_a_copy()};
    ICantBeCopied b{::std::move(make_a_copy())};
}

关于c++ - 为什么复制和 move 构造函数以相同数量的 memcopies 结束?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58599419/

相关文章:

c++ - 在 const 声明的对象上修改可变是未定义的行为吗?

c++ - 使用正则表达式的高效字数统计方法

ios - iOS 中 std::make_shared 调用析构函数的可变版本

c++ - decltype 需要实例化对象

c++ - 为什么这段代码试图调用复制构造函数?

c++ - 跟踪对复制构造函数的调用

c++ - 在访问 vector<bool> 中的元素地址时获取临时地址

c++ - 如何正确声明变量

c++ - Clion如何部署项目?

c++ - 简单的链表,带有完整的五法则