gpt4 book ai didi

c++ - 返回语句异常

转载 作者:可可西里 更新时间:2023-11-01 16:39:52 25 4
gpt4 key购买 nike

考虑以下函数:

Widget f(Widget w) {
return w;
}

假设 Widget 同时实现复制和移动构造函数,根据 C++ 标准,w 必须被视为 rvalue 对象return 语句,以防编译器不认为复制省略是更好的选择。

另一方面,考虑以下版本:

Widget f(Widget&& w) {
return w;
}

与第一个版本相反,根据 Effective Modern C++Item 25,作者似乎暗示返回 w 会当然调用复制构造函数。换句话说,他建议改为返回 std::move(w),以使编译器使用(可能更快的)移动构造函数。

你能解释一下为什么以 Widget&& 作为参数的 f() 的第二个版本与以 Widget 为参数的第一个版本不等价吗相对于在 return 语句中调用的构造函数的值,还考虑到在两个函数的主体中,表达式 w 引用 lvalue?

演示行为的完整示例:

#include <iostream>

struct Widget
{
Widget() { std::cout << "constructed" << std::endl; }
~Widget() { std::cout << "destructed" << std::endl; }
Widget(const Widget&) { std::cout << "copy-constructed" << std::endl; }
Widget(Widget&&) { std::cout << "move-constructed" << std::endl; }
};

Widget
f1(Widget w)
{
return w;
}

Widget
f2(Widget&& w)
{
return w;
}

int
main()
{
f1(Widget {});
std::cout << std::endl;
f2(Widget {});
}

输出:

constructed
move-constructed
destructed
destructed

constructed
copy-constructed
destructed
destructed

最佳答案

隐式移动的标准基于何时允许复制省略,但有一些异常(exception)。对于不是函数参数或 catch 参数的局部对象,允许复制省略。隐式移动将作为函数参数的局部对象添加到其中。所以它允许它在 Widget f(Widget w) { return w; },但不在 Widget f(Widget&& w) { return w; },其中 w 是局部变量,但不是局部对象。

在当前不允许的几种情况下,隐式移动是安全的,包括在您的示例中。但是,隐式移动是根据具体情况仔细考虑的,您的示例尚未被考虑,或者尚未被认为是安全的。

非常类似的例子 Widget f(Widget& w) { return w; } 将是不安全的:调用者正在执行 Widget w; f(w); 不能期望 w 被编译器静默清除。

这个非常相似的例子显示了启用隐式移动的风险有多大,以及为什么你必须把它拼写出来,即使它对你来说似乎很明显。引用“局部变量”的措辞将覆盖Widget&& w将覆盖Widget& w。在不安全的地方进行隐式移动比在安全的地方错过隐式移动更糟糕,必须绝对确定措辞涵盖安全情况。

关于c++ - 返回语句异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28572512/

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