将 std::string ctor 参数传递给具有移动语义的 pimpl 中的 impl
Posted
技术标签:
【中文标题】将 std::string ctor 参数传递给具有移动语义的 pimpl 中的 impl【英文标题】:Pass a std::string ctor parameter to impl in pimpl with move semantics 【发布时间】:2021-10-18 21:30:28 【问题描述】:这是通过移动语义将 std::string 参数传递给 Impl 的构造函数的正确方法吗?
#include <string>
#include <memory>
using namespace std;
class Foo
struct Impl;
unique_ptr<Impl> impl_;
public:
Foo(string s);
;
struct Foo::Impl
string s_;
Impl(string s) : s_(std::move(s))
;
Foo::Foo(string s) : impl_(make_unique<Foo::Impl>(move(s)))
或者应该将Impl的ctor定义为:
Impl(string&& s) : s_(std::move(s))
【问题讨论】:
使用右值引用可能会使代码更快一点,因为它会减少移动。与往常一样,尝试两者并衡量结果。根据字符串的大小,以及如果您使用 SSO 实现,删除一个移动可能会产生很大的不同,或者它可能并不重要。 对于右值参考案例,我需要 Impl 的 ctor 中的 std::move() 吗?无论有没有移动调用,它都可以编译。 是的,您仍然需要使用std::move
。任何有名字的东西都是左值,包括右值引用,所以如果你想让移动发生,你需要用std::move
将它转换回右值。
我明白了,所以没有 std::move() s_ 只会被复制构造?
是的。没有它,你就有了一个左值,除非你使用std::move
,否则它们永远不会被移动。该语句有几个边缘情况,但它们处理具有自动存储持续时间的本地对象,并且要么被返回,要么被抛出本地范围之外。
【参考方案1】:
这是正确的做法吗
Impl(string s) : s_(std::move(s))
这很好。
或者应该将Impl的ctor定义为:
Impl(string&& s)
这通常不太有用,因为您无法将左值字符串作为参数传递。也就是说,如果 Foo::Foo(string s)
是调用 Impl
的构造函数的唯一上下文,那么在实践中缺乏一般用途不会成为问题,因此这也可以。
附:一旦您在单独的翻译单元中实际定义了Impl
,您会发现您需要用户声明Foo
的特殊成员函数(析构函数、移动、赋值),因为它们的定义取决于Impl
的定义。
【讨论】:
以上是关于将 std::string ctor 参数传递给具有移动语义的 pimpl 中的 impl的主要内容,如果未能解决你的问题,请参考以下文章
EXC_BAD_ACCESS(code = 1,address = 0x0)当将std :: map作为参数传递给虚拟函数调用时发生
如何将 POST 参数传递给 Durable Function,然后将此参数传递给 Timer Triggered 函数