首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >移动语义和重载

移动语义和重载
EN

Stack Overflow用户
提问于 2022-10-08 20:16:47
回答 1查看 64关注 0票数 0

我认为我对rvalue引用和move语义的理解有一些漏洞。

就我现在所理解的rvalue引用而言,我可以通过两种方式实现函数f,这样它就可以从移动语义中获益。

第一个版本:实现这两个版本

代码语言:javascript
复制
void f(const T& t);
void f(T&& t);

这将导致相当多的冗余,因为这两个版本都有(几乎)相同的实现。

第二版:仅实现

代码语言:javascript
复制
void f(T t);

调用f将导致调用T的副本或移动构造函数。

有个问题。这两个版本的比较如何?我怀疑:在第二个版本中,动态分配的数据的所有权可能被移动构造函数移动,而t中的非动态分配数据及其成员需要被复制。在第一个版本中,两个版本都没有分配任何额外的内存(除了引用后面的指针)。

如果这是正确的,我是否可以避免编写f的实现基本上两次,而没有第二个版本的缺点?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-10-08 20:52:24

如果需要接受T&&参数,这通常意味着要将对象移到某处并保留它。这类函数通常与const T&重载配对,因此它可以同时接受rvalue和lvalue。

在这种情况下,第二个版本(只有一个以T作为参数的重载)总是效率较低,但很可能不太有效。

对于第一个版本,如果传递一个lvalue,则函数接受一个引用,然后生成一个副本将其存储在某个地方。那是一份副本结构或任务。如果传递一个rvalue,则函数再次接受引用,然后移动对象来存储它。这是建筑或任务的一步。

对于第二个版本,如果您传递一个lvalue,它将被复制到参数中,然后函数可以移动它。如果您传递一个rvalue,如果被移动(假设该类型有一个move构造函数)到参数中,那么这个函数也可以移动它。在这两种情况下,这是比第一个版本多一个移动构造或分配。

还请注意,在某些情况下可以发生复制省略

第二个版本的好处是您不需要多个重载。对于第一个版本,需要对需要复制或移动的n个参数进行2^n重载。

在只有一个参数的简单情况下,我有时会这样做以避免重复代码:

代码语言:javascript
复制
void f(const T& t) {
    f_impl(t);
}
void f(T&& t) {
    f_impl(std::move(t));
}

// this function is private or just inaccessible to the user
template<typename U>
void f_impl(U&& t) {
    // use std::forward<U>(t)
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74000262

复制
相关文章

相似问题

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