C++ 始终在构造函数中引用常量?

C++ Always Const Reference in Constructor?

提问人:Caresi 提问时间:9/20/2015 最后编辑:pfabriCaresi 更新时间:5/6/2019 访问量:4562

问:

因此,请考虑以下代码:

#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;
}

这将打印出:

复制了!

复制了!

是的,没错,它复制了两次!

当我们传递给构造函数时,第一个副本发生了。 当我们从构造函数复制到成员变量时,就会发生第二次复制。dataB'sdata

我们知道我们不能低于 1 个副本(除非我们去)。那么我们为什么不总是写:heap & pointers

B (const A& data, const int& foo, const SomeOtherType& bar, const float& aFloatyNumber)...等等。

我知道按值传递 int、float 等很便宜。但是,通过始终将参数作为参数,我们将保证少 1 个副本。const refConstructor

C++ C++11 构造函数 Pass-By-Reference Pass-By-Value

评论

4赞 Igor Tandetnik 9/20/2015
we will garantie 1 less copy只有当副本很昂贵时,这才重要。复制一个很便宜 - 比通过引用访问相同的间接成本便宜。intint
0赞 vsoftco 9/20/2015
没有人阻止你使用。对于 POD,这没有任何区别,可能编译器优化了间接并简单地复制了 etc。const A& dataint
0赞 danielschemmel 9/20/2015
因为您要查找的语义是移动语义(带有 rvalue-references)而不是副本。
0赞 StoryTeller - Unslander Monica 9/20/2015
c++ 中的所有内容都是通过“引擎盖下”的值传递的,这是从 c 继承而来的。由于引用可以并且通常使用指针实现,因此您仍然必须为每个函数调用复制基础指针。这将比复制 int 更昂贵,因为您最终会得到一个间接的 in-end。
0赞 Galik 9/20/2015
我们总是将 const ref 用于非平凡类型。除非我们使用移动语义。而不仅仅是构造函数。除非您特别想要一份副本。

答:

0赞 ypnos 9/20/2015 #1

基元类型在不需要时不会被复制。它们一直保留在堆栈或寄存器中,直到最后。

5赞 Dietmar Kühl 9/20/2015 #2

如果你移动你正在使用的对象,你实际上应该通过引用来传递你的参数,可能作为一个 .如果您确实使用参数,则应按值传递移动感知类型的对象(即定义移动构造函数的类型)移动它。也就是说,如果是移动感知的,即有一个构造函数,您将使用:T const&AA::A(A&&)

B(A data, int foo) : data(std::move(data)), foo(foo) {
}

如果您的类型不是移动感知的,或者您不需要从构造中挤出最后一点性能,或者类型是仅移动的,则可以安全地传递对象。T const&

1赞 Praveen Pandey 9/20/2015 #3

您的查询有矛盾。

在第一种情况下,当你传递值时,你正在使用第一个对象来制作其他对象,这就是为什么需要再次调用构造函数的原因。

其次,通过值传递对象作为引用和基元是为了优化大小。

如果你想将 int 作为 const ref 或指针传递,那没关系,你可以这样做,但你能从中得到什么吗?

如果要将该值复制到其他变量的调用函数中,则将再次调用构造函数。

因此,如果要将值存储在被调用函数的局部变量中,则必须再次调用构造函数,而不管它是通过值还是引用传递的。