gpt4 book ai didi

c++ - 按值传递与 const & 和 && 重载

转载 作者:IT老高 更新时间:2023-10-28 12:34:49 25 4
gpt4 key购买 nike

因此,在查看 move 语义后,我发现一般共识是在您打算转移所有权时按值传递。但是在 Scott Meyer's talk on Universal references我注意到 std::vector::push_back 有 2 个重载:

void push_back( const T& value );
void push_back( T&& value );

所以我想,void push_back( T value ); 还不够吗?我问了几个人,最终得出了以下测试用例:

#include <memory>
#include <iostream>
#include <type_traits>

struct A
{
A() { std::cout << "A Default constructor\n"; }
A(const A &) { std::cout << "A Copy\n"; }
A(A &&) { std::cout << "A Move\n"; }
};

std::aligned_storage<sizeof(A)> contents;
A& alias = *reinterpret_cast<A*>(&contents);

void ByVal(A a)
{
new (&contents) A(std::move(a));
alias.~A();
}

void ByLCRef(A const& a)
{
new (&contents) A(a);
alias.~A();
}

void ByRRef(A&& a)
{
new (&contents) A(std::move(a));
alias.~A();
}

int main()
{
A a;
std::cout << "\n";
std::cout << "ByVal(a);\n";
ByVal(a);
std::cout << "ByVal(std::move(a));\n";
ByVal(std::move(a));
std::cout << "ByVal(A());\n";
ByVal(A());
std::cout << "ByLCRef(a);\n";
ByLCRef(a);
std::cout << "ByRRef(std::move(a));\n";
ByRRef(std::move(a));
std::cout << "ByRRef(A());\n";
ByRRef(A());
}

这会产生以下内容:

A Default constructor

ByVal(a);
A Copy
A Move
ByVal(std::move(a));
A Move
A Move
ByVal(A());
A Default constructor
A Move
ByLCRef(a);
A Copy
ByRRef(std::move(a));
A Move
ByRRef(A());
A Default constructor
A Move

如您所见,与一对引用重载相比,ByVal 产生了 1 个额外的 move 。所以问题是:值得吗?你什么时候会创建两个重载而不是一个简单的按值传递函数?

最佳答案

As you can see, ByVal produces 1 extra move compared to pair of reference overloads. So the question is: is it worth it? When would you create two overloads instead of one simple pass by value function?

+1 大多数提出这个问题的人都懒得做分析。所以你得到我的赞成,因为你自己做作业。 :-)

是否值得取决于 move 构造函数的成本,以及函数需要多少参数。在一种极端情况下,如果 move 构造函数不是那么快,您可能会非常关心消除它们(赞成 const&、&& 重载解决方案)。在另一个极端,如果你的函数有 4 个参数,每个参数都需要左值/右值处理,你可能不愿意编写 16 个重载来涵盖所有情况。这是需要维护的大量代码,而固有的代码复杂性会招致错误。所以按值方法看起来更有吸引力(不需要重载)。

所以恕我直言,“是否值得”这个问题没有一般的答案。最好的答案是让自己了解每种解决方案的成本,就像您已经做过的那样,并根据具体情况做出工程判断。

更新

vector<T>::push_back 的情况下恕我直言,const&, && 重载解决方案是值得的。只有一个参数,我们不知道 move 构造函数有多昂贵。事实上,我们甚至不知道 if 是否存在 move 构造函数。修改您的实验以测试后一种情况(删除 move 构造函数):

ByVal(a);
A Copy
A Copy

ByLCRef(a);
A Copy

您要支付一份或两份复制您的A进入vector ?

即你对参数的了解越少,你就越倾向于性能方面,特别是如果你正在编写像 std::vector 这样频繁使用的东西。 .

关于c++ - 按值传递与 const & 和 && 重载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14185985/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com