- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我编写了自己的字符串类型(Str
)来演示基本的构造函数、析构函数和赋值运算符;而且,我可以看到它们都在 C++17 中执行,除了 move 构造函数。
显然,由于返回值优化 (RVO), move 构造函数不再被广泛使用。
move 构造函数是否仅在响应显式调用 std::move
时调用?
还有什么时候可以调用它?
它主要是因为 RVO 而过时了吗?
这是我的 Str
类型:
struct Str {
Str(): p(nullptr) {}
Str(const char* s) { cout << "cvctor \"" << s << "\"\n"; copy(s); }
Str(const Str& s): p(nullptr) { cout << "cpctor deep\""<<s.p<<"\"\n"; copy(s.p); }
Str( Str&& s) { cout << "mvctr shallow \"" << s.p << "\"\n"; p = s.p; s.p=nullptr; }
const Str& operator=(const Str& s) { cout << "op=\""<<s.p<<"\"\n"; copy(s.p); return *this; }
const Str& operator=( Str&& s) { cout << "op= shallow \""<<s.p<<"\"\n"; p=s.p; s.p=nullptr; return *this; }
~Str(){ if ( p != nullptr ) { cout << "dtor \"" << p << "\"\n"; delete [] p; } }
private:
char* p = nullptr;
char* copy(const char* s)
};
最佳答案
返回值优化并不是使用 move 构造函数的唯一点。每次您想从 rvalue
构造某种类型的值时,都会使用 move 构造函数。
您基本上是将两个问题合二为一。让我们开始吧
Is the move constructor only called in response to explicitly calling std::move?
move 构造函数和 std::move
是切线相关的,但本质上是非常独立的。每次从相同类型的 rvalue
初始化变量时,都会调用 move 构造函数。另一方面,std::move
可以明确地从所谓的 lvalue
到这样的 rvalue
但它不是唯一的办法。
template<typename T>
void foo(T&& value) { // A so-called universal reference
T other_value = std::forward<T>(value);
}
foo( string{"some string"} ); // other_value is move initialized
你看,std::forward
是另一种获取rvalue
的方法。实际上,"some string"
也会在上面的代码中生成 rvalue
,类型为 const char*
。
间奏曲时间到了。如果您听到 rvalue
,您可能会想到 &&
,它是一个 rvalue-reference
。这是微妙的不同。问题是给任何东西命名都会使它成为左值
。所以下面的代码:
foo(string&& value) {
T other_value = value;
}
foo( "some_string" ); // other_value is STILL copy initialized
foo(string&& value) {
T other_value = std::move(value);
}
foo( "some_string" ); // other_value is now properly move initialized
考虑&&
的正确方法是这样的引用可以用rvalue
初始化,但它本身并不总是这样的rvalue
。有关详细信息,另请参阅 here
Is it mostly obsolete because of RVO?
除了 RVO 之外,还经常使用 move 构造函数的两个值得注意的例子
进入方法参数
void foo(string value);
// Somewhere else
string& some_string = get_me_a_string();
foo( ::std::move(some_string) ); // Uses move constructor to initialize value
some_string.clear(); // Most probably a no-op
// Doing this leaves an empty some_string
请注意,在上面的示例中,some_string
是一个引用这一事实与是否使用 move 构造无关。这是一个明确的引用,RVO 可能并不总是可能的。在这种情况下,在 some_string
被移出后,将处于未指定但有效的状态,这是一种奇特的方式,表示不会发生未定义的行为并且引用仍然有效。
进入田野
class FooBar {
string fooField;
//Constructor
FooBar( string bar )
: fooField( ::std::move(bar) ) // Uses move constructor to initialize fooField
{ }
}
关于c++ - C++ move 构造函数过时了吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51959379/
我是非洲的一名学生,在我们的土地上,确实存在缓慢且昂贵的互联网连接,这就是为什么每当我们听到安装软件的“在线存储库”方法这个词时都会害怕得发抖。该死的,这通常意味着你必须去别处看看。 问题。(如果没有
我正在使用 OpenCV 1 进行一些图像处理,并且对 cvSetErrMode 函数(它是 CxCore 的一部分)感到困惑。 OpenCV 具有三种错误模式。 叶:调用错误处理程序后程序终止。 父
安装新版 IDEA.14 后,(maven)项目的部署显着增加(从 15 秒增加到 47 秒)。 最佳答案 原因: IDEA 使用 捆绑 Maven的版本 解决方案:设置 (ctrl+alt+S) -
在 .NET 中,您可以将某些方法标记为过时,以便开发人员在尝试使用已弃用的方法时收到警报。 Private Sub FormerMethod() 问题是您只能在您控制的类中执行此操作。当您希望开发
一段时间以来,我一直在尝试自己解决这个问题,但一直没有成功。当我大约有 10% 的时间重新部署我的 Rails 应用程序时,就会发生这种情况。其他 90% 的时间部署顺利进行。 我试了又试,还是没成功
已关闭。此问题需要 debugging details 。目前不接受答案。 编辑问题以包含 desired behavior, a specific problem or error, and the
我正在学习 HTTP/2 协议(protocol)。它是一个带有小消息帧的二进制协议(protocol)。它允许在单个 TCP 连接上进行流复用。从概念上讲,它似乎与 WebSockets 非常相似。
在 Matlabs 的最新版本中,specgram 函数被 spectrogram 取代,文档说明: Note. To obtain the same results for the removed
我们试图在构建时标记外部类型(如 ConfigurationManager)的使用。 自定义代码分析字典可以提供帮助 [1],但仅限于项目中包含源代码的情况。同样,Obsolete 属性适用于项目中包
我将 Anaconda 与 Python 3 结合使用,并尝试安装 cc 包,这是 uber h3 包的要求。 尝试通过以下方式在 anaconda 命令行中安装时: pip install cc 我
我在 Razor 中创建了一个专门用于显示货币的显示模板,现在我想在我的代码中删除它并替换为接受字符串格式(我可以将其设置为“C”)的标准文本显示模板。 然而,出现了很多次,所以我想使用类似 [Obs
我希望我的网站具有如下所示的 URL: example.com/2010/02/my-first-post 我有我的 Post带 slug 的模型字段('我的第一篇文章')和 published_on
4.7 并喜欢在 qgraphicsview 上叠加两个图像。顶部的图像应是半透明的,以便能够透过它看到。最初,两个图像都是完全不透明的。我期望存在一些为每个像素设置全局 alpha 值的函数,但似乎
总结: 我在我的 Swift 代码中犯了一个错误,我已经修复了它。然后我问自己为什么会这样,我该如何避免。我尝试了一些方法,但没有任何帮助。 我把错误和我的想法放在下面。我希望你能教我避免这种错误的正
我正在尝试重命名在 SVN 中跟踪的 Java 包。这一切似乎都有效。它将代码移动到新包等。然而,噩梦就在那时开始,乐趣就开始了,这取决于你的观点。摆脱旧包很难。 我陷入了“过时”或“不存在”消息的循
我们使用 NLog 或 Serilog 进行日志记录。我们正忙于将系统从 ASP.NET 移植到 ASP.NET Core,这 has logging built in . 理想情况下,我们希望放弃
ETag header 的定义 ( https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/ETag ): The ETag HTTP re
我是一名优秀的程序员,十分优秀!