我应该总是在“sink”构造函数或setter参数上移动
Should I always move on `sink` constructor or setter arguments?
struct TestConstRef {
std::string str;
Test(const std::string& mStr) : str{mStr} { }
};
struct TestMove {
std::string str;
Test(std::string mStr) : str{std::move(mStr)} { }
};
看完 GoingNative 2013 后,我明白了 sink 参数应该始终按值传递并随std::move
移动。TestMove::ctor
应用这个成语的正确方法吗?有没有TestConstRef::ctor
更好/更有效的情况?
琐碎的二传手呢?我应该使用以下成语还是传递const std::string&
?
struct TestSetter {
std::string str;
void setStr(std::string mStr) { str = std::move(str); }
};
简单的答案是:是的。
原因也很简单,如果您按值存储,则可能需要移动(从临时)或复制(从l值)。让我们看看在这两种情况下,以两种方式会发生什么。
从临时
- 如果你通过 const-ref 获取参数,则临时参数绑定到 const-ref 并且无法再次移动,因此您最终会制作一个(无用的)副本。
- 如果您按值获取参数,则从临时(移动)初始化值,然后您自己从参数中移动,因此不会进行复制。
限制:一个没有有效移动构造函数(如std::array<T, N>
)的类,因为那时你做了两个副本而不是一个。
从 l 值(或常量临时,但谁会这样做......
- 如果你通过 const-ref 获取参数,那里什么都不会发生,然后你复制它(不能从它移动),因此制作了一个副本。
- 如果按值获取参数,则将其复制到参数中,然后从参数中移动,从而创建单个副本。
一个限制:相同的...移动类似于复制的类。
因此,简单的答案是,在大多数情况下,通过使用接收器可以避免不必要的副本(用移动替换它们)。
唯一的限制是移动构造函数与复制构造函数一样昂贵(或接近昂贵)的类;在这种情况下,有两个移动而不是一个副本是"最糟糕的"。值得庆幸的是,这样的类很少见(数组是一种情况)。
有点晚了,因为这个问题已经有一个公认的答案,但无论如何......这是一个替代方案:
struct Test {
std::string str;
Test(std::string&& mStr) : str{std::move(mStr)} { } // 1
Test(const std::string& mStr) : str{mStr} { } // 2
};
为什么会更好?考虑两种情况:
从临时(案例// 1
)
str
只需要一个移动构造函数。
从 l 值(案例 // 2
)
str
只需要一个复制构造函数。
它可能不会比这更好。
但是等等,还有更多:
调用方不会生成额外的代码!复制或移动构造函数(可能是内联的,也可能不是内联的)现在可以存在于被调用函数的实现中(这里:Test::Test
),因此只需要该代码的单个副本。如果使用按值参数传递,则调用方负责生成传递给函数的对象。这可能会在大型项目中加起来,如果可能的话,我会尽量避免它。
- 如何反转整数参数包
- 使用C++库在Android项目中修改gradle中的cmake参数,用于插入指令的测试
- 如何使用默认参数等选择模板专业化
- 模板参数替换失败,并且未完成隐式转换
- 具有默认模板参数的多态类的模板推导失败
- lambda参数转换为constexpr技巧,然后获取带链接的数组
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 函数调用中参数的顺序重要吗
- 部分定义/别名模板模板参数
- 模板-模板参数推导:三个不同的编译器三种不同的行为
- 使用不带参数的函数访问结构元素
- C++中大多数/所有 setter 函数的参数是否应该写为常量引用?
- C++ - 调用 setter 的函数 - 如何装饰参数
- 当我们有用于设置值的 setter 时,为什么我们使用参数化构造函数
- 构造函数应该接受参数还是应该创建setter
- 当setter方法参数是C++中的引用时会发生什么
- 我应该总是在“sink”构造函数或setter参数上移动
- 这是更有效的Qt:构造函数与参数或默认构造函数与setter之后
- c++ 11 Setter函数参数传递nullptr
- const或ref或const ref或value作为setter函数的参数