提问人:Caresi 提问时间:9/20/2015 最后编辑:pfabriCaresi 更新时间:5/6/2019 访问量:4562
C++ 始终在构造函数中引用常量?
C++ Always Const Reference in Constructor?
问:
因此,请考虑以下代码:
#include <iostream>
using namespace std;
class A {
public:
A() = default;
A(const A& rhs) {
cout << "Copy was made!" << endl;
}
};
class B {
public:
A data;
int foo;
B(A data, int foo) : data(data), foo(foo) {
}
};
int main() {
A data;
B foo(data, 10);
return 0;
}
这将打印出:
复制了!
复制了!
是的,没错,它复制了两次!
当我们传递给构造函数时,第一个副本发生了。
当我们从构造函数复制到成员变量时,就会发生第二次复制。data
B's
data
我们知道我们不能低于 1 个副本(除非我们去)。那么我们为什么不总是写:heap & pointers
B (const A& data, const int& foo, const SomeOtherType& bar, const float& aFloatyNumber)
...等等。
我知道按值传递 int、float 等很便宜。但是,通过始终将参数作为参数,我们将保证少 1 个副本。const ref
Constructor
答:
基元类型在不需要时不会被复制。它们一直保留在堆栈或寄存器中,直到最后。
如果你不移动你正在使用的对象,你实际上应该通过引用来传递你的参数,可能作为一个 .如果您确实使用参数,则应按值传递移动感知类型的对象(即定义移动构造函数的类型)并移动它。也就是说,如果是移动感知的,即有一个构造函数,您将使用:T const&
A
A::A(A&&)
B(A data, int foo) : data(std::move(data)), foo(foo) {
}
如果您的类型不是移动感知的,或者您不需要从构造中挤出最后一点性能,或者类型是仅移动的,则可以安全地传递对象。T const&
您的查询有矛盾。
在第一种情况下,当你传递值时,你正在使用第一个对象来制作其他对象,这就是为什么需要再次调用构造函数的原因。
其次,通过值传递对象作为引用和基元是为了优化大小。
如果你想将 int 作为 const ref 或指针传递,那没关系,你可以这样做,但你能从中得到什么吗?
如果要将该值复制到其他变量的调用函数中,则将再次调用构造函数。
因此,如果要将值存储在被调用函数的局部变量中,则必须再次调用构造函数,而不管它是通过值还是引用传递的。
评论
we will garantie 1 less copy
只有当副本很昂贵时,这才重要。复制一个很便宜 - 比通过引用访问相同的间接成本便宜。int
int
const A& data
int