- iOS/Objective-C 元类和类别
- objective-c - -1001 错误,当 NSURLSession 通过 httpproxy 和/etc/hosts
- java - 使用网络类获取 url 地址
- ios - 推送通知中不播放声音
我对以下“规则”感到满意:当您打算存储 对象时按值接受,而当您只需要访问它时按常量引用接受。这样,您(类的编写者)不会选择是否复制类变量的用户或是否 move 它,他们会选择。但在使用过程中,我越来越不确定这个建议是否正确; move 在成本操作上不是统一的...
struct Thing
{
std::array<int, 10000> m_BigArray;
};
class Doer
{
public:
Doer(Thing thing) : m_Thing(std::move(thing)) {}
private:
Thing m_Thing;
};
int main()
{
Thing thing;
Doer doer1(std::move(thing)); // user can decide to move 'thing'
// or
Doer doer2(thing); // user can decide to copy 'thing'
}
在上面的例子中, move 和复制一样昂贵。因此,不是采用 const 引用并复制对象一次,而是最终 move 它(有效地复制它)两次。用户对你的论点做了一次,然后你又对你的成员做了一次。
即使 move 比复制便宜得多,这种情况也会进一步恶化(假设 move 的东西是下面的一些未知成本,但比复制便宜):
struct A
{
A(Thing thing) : m_Thing(std::move(thing)) {}
Thing m_Thing;
};
struct B : A
{
B(Thing thing) : A(std::move(thing)) {}
};
struct C : B
{
C(Thing thing) : B(std::move(thing)) {}
};
struct D : C
{
D(Thing thing) : C(std::move(thing)) {}
};
在这里,您将得到 1 个拷贝和 4 个 move ,或 5 个 move 。如果所有的构造函数都接受一个 const 引用,那么它只会是 1 个拷贝。现在我必须权衡什么走法昂贵,1 个拷贝还是 5 个走法。
处理这些情况的最佳建议是什么?
最佳答案
What's the best advice for handling these situations?
我最好的建议是做你正在做的事情:为自己考虑。不要相信你听到的一切。测量。
下面我获取了您的代码并使用打印语句对其进行了检测。我还添加了第三种情况:从纯右值初始化:
测试以两种方式尝试:
const&
和 &&
传递时重载:代码:
#include <utility>
#include <iostream>
struct Thing
{
Thing() = default;
Thing(const Thing&) {std::cout << "Thing(const Thing&)\n";}
Thing& operator=(const Thing&) {std::cout << "operator=(const Thing&)\n";
return *this;}
Thing(Thing&&) {std::cout << "Thing(Thing&&)\n";}
Thing& operator=(Thing&&) {std::cout << "operator=(Thing&&)\n";
return *this;}
};
class Doer
{
public:
#if PROCESS == 1
Doer(Thing thing) : m_Thing(std::move(thing)) {}
#elif PROCESS == 2
Doer(const Thing& thing) : m_Thing(thing) {}
Doer(Thing&& thing) : m_Thing(std::move(thing)) {}
#endif
private:
Thing m_Thing;
};
Thing
make_thing()
{
return Thing();
}
int main()
{
Thing thing;
std::cout << "lvalue\n";
Doer doer1(thing); // user can decide to copy 'thing'
std::cout << "\nxvalue\n";
Doer doer2(std::move(thing)); // user can decide to move 'thing'
std::cout << "\nprvalue\n";
Doer doer3(make_thing()); // user can decide to use factor function
}
对我来说,当我使用 -DPROCESS=1 编译时,我得到:
lvalue
Thing(const Thing&)
Thing(Thing&&)
xvalue
Thing(Thing&&)
Thing(Thing&&)
prvalue
Thing(Thing&&)
还有 -DPROCESS=2:
lvalue
Thing(const Thing&)
xvalue
Thing(Thing&&)
prvalue
Thing(Thing&&)
因此,对于左值和 xvalue 情况,通过值传递比通过重载引用传递需要额外的 move 构造。正如您所指出的,搬家建筑不一定便宜。它可能与复制构造一样昂贵。从好的方面来说,您只需编写 1 个按值传递的重载。通过重载引用传递需要 2^N 次重载,其中 N 是参数的数量。在 N==1 时相当可行,在 N==3 时变得笨拙。
另外,正如您所指出的,您的第二个示例只是您的第一个示例。
当性能是您最关心的问题时,尤其是当您不能指望便宜的 move 构造函数时,请传递重载的右值引用。当您可以依靠便宜的 move 构造,和/或您不想处理不合理的(您可以为自己定义不合理的)重载数量时,请使用按值传递。没有一个答案在任何情况下都对每个人都是正确的。 C++11 程序员仍然需要思考。
关于C++11 最佳实践 : When to accept by value vs const&?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14921364/
标记为家庭作业,因为这是我写的期中问题,但我不明白答案。我被要求在以下语句中解释每个 const 的用途: const char const * const GetName() const { ret
const int* const fun(const int* const& p) const; 我试图弄清楚这个给定函数原型(prototype)的输入参数。我在这两个之间争论,不确定哪个是正确的。
下面的代码用于在同时存在 const 和非 const getter 时减少代码重复。它从非 const 创建 const 版本。我搜索了一下,很多人说我应该从 const 创建非 const 版本。
据我所知,TypeScript 查看了 const string变量作为一个不可变的类型变量,只有那个值,没有其他可能的值。一直以为加as const那是多余的。 为什么我在示例的第二部分得到以下内容
我有一个具有以下签名的方法: size_t advanceToNextRuleEntryRelatedIndex( size_t index, size_t nStrings, char const
首先,有什么区别: (1) const char* (2) char const* (3) const char const* 我相当确定我完全理解这一点,但我希望有人能具体地给我一个句子,这样它就会
这里是新手! 我正在阅读一段代码,我看到作者经常写一个成员函数作为 const int func (const scalar& a) const // etc 你看这里有三个const,现在我明白了中
我总是搞乱如何正确使用 const int*、const int * const 和 int const *。是否有一套规则来定义你可以做什么和不能做什么? 我想知道在赋值、传递给函数等方面所有该做和
我见过人们将 const 用作函数参数的代码。使用 const* 与 const * const 有什么好处?这可能是一个非常基本的问题,但如果有人能解释一下,我将不胜感激。 Bool IsThisN
我总是搞乱如何正确使用 const int*、const int * const 和 int const *。是否有一套规则来定义你可以做什么和不能做什么? 我想知道在赋值、传递给函数等方面所有该做和
这个问题在这里已经有了答案: What is the difference between const int*, const int * const, and int const *? (23 个
如果引用的对象不是 const 对象,那么引用“const”关键字的目的是什么? r1 和 r2 的作用(如下)有什么不同吗? int i = 42; // non const object cons
friend 让我解释原因 const const const const const int const i = 0; 是有效的语法。我拒绝对这个话题有任何想法。虽然我很好奇它是否只是语法问题? 编
我总是搞砸如何正确使用 const int*、const int * const 和 int const *。是否有一套规则来定义你能做什么和不能做什么? 我想知道在分配、传递给函数等方面的所有注意事
常量在 const char* push(const char * const &&_data); 表示无法更改引用的内容。为什么我不能将 const char* 传递给 push? 最佳答案 您的代
我有一个关于在函数参数中涉及指针的最佳实践以及它们是否应该指定为 *const 的问题或 const *const .我知道对于 const 的使用或过度使用存在不同的意见。 ,但至少有一些用途是捕捉
我目前正在为我的类(class)写一个作业,它应该充当一个非常基本的外壳。我快完成了,但是我遇到了 execvp 和我的参数字符数组的问题。这是我的代码的一小段。 //Split the left c
所以,我知道了char const *、char * const 和char const * const 之间的区别。那些是: char* the_string : I can change the
我正在运行一些示例程序以重新熟悉 C++,我遇到了以下问题。首先,这里是示例代码: void print_string(const char * the_string) { cout << t
我正在为系统中的编译错误而苦苦挣扎,这是代码 struct Strless : public binary_function { public : bool operator()(cons
我是一名优秀的程序员,十分优秀!