在c++中必须通过引用传递类吗

Is it obligatory to pass classes by reference in c++

本文关键字:引用 c++      更新时间:2023-10-16

我在c++中进行了一次期中考试,我们的作业之一是编写一个类,该类重载<<运算符,以便我们可以将该类的私有字段打印到std::ostream,如下所示:

Crate c1(2600, 9500);
Crate c2;
cout << c1 << ", " << c2 << endl;

必须打印Crate weight: 2600 Crate value: 9500, Crate weight: 0 Crate value: 0

我的实现是

class Crate {
    int weight;
    int value;
public:
    Crate ():weight(0), value(0) {}
    Crate (int w, int v);
    Crate& operator+= (Crate& c);
    int operator+= (int& w);
    friend ostream& operator<< (ostream& out, Crate c) {
        out << "Crate weight: " << c.weight;
        out << " Crate value: " << c.value;
        return out;
    }
};

然而,对于重载的<<运算符,我得到了0/3分,我的解决方案和评估模板之间的唯一区别是,我通过值传递Crate c,而他们通过引用传递。

当然,如果类具有动态分配的成员变量,我将不得不通过引用传递它的实例,但这里的情况并非如此。

我知道cppreference.com上提供的例子使用了const引用,但有没有严格的规则规定在执行此操作时必须使用const引用?

我知道我的解决方案将weightvalue都复制到堆栈中,而不是只复制指向对象的指针,但堆栈上的+4字节(在32位系统的情况下)真的是一个很大的问题,还是我遗漏了更严重的东西(比如某种内存泄漏)?

我还检查了这两个解决方案的分解,但我找不到任何能使我的解决方案价值为零的东西。

我也问过我的教授,但他们开始讨论将其作为const通过,但我不认为这会使这个解决方案在有效/无效方面变得更好。另一位教授告诉我,"这在语法上完全不正确。"然而,它是用Visual Studio和MinGW编译的,所以我也无法理解。

还请注意,这是一门针对电气工程师的课程。

是否必须在c++中通过引用传递类

没有。

"将其作为const传递"这太傻了,如果你通过值传递,那么如果你将参数标记为const,对外界来说也没关系。

为了尽可能直接地回答你的问题,按值取另一个类并没有错。当对象较小时,最好按值传递。在您的情况下,在典型的64位平台上,大小差异为0(每int 2*4字节,而一个8字节指针)。所以你的"+4字节在堆栈上"实际上不存在,它是相同大小的

我预测优化编译器会重写您的代码,使其按值取Crate,即使您声明它为按引用取。这将是出于空间位置和访问方便的原因。如果传递了一个指针,您需要跟随指针到达数据成员,这会增加一个步骤。

你的教授给你0分是错误的,除非课程中有明确的要求,即所有运算符都必须采用参考参数。const CrateCrate的问题并不重要。

您不应该收到0,但也不应该收到全部信用。

friend ostream& operator<< (ostream& out, Crate c) 

每次调用时都要创建一个副本,这可能效率很低。为了避免那些你想通过引用传递的副本,比如

friend ostream& operator<< (ostream& out, Crate& c)

但这引入了一个新问题,这是您的第一个版本所没有的,即通过引用传递,您需要为函数提供一个左值。你将无法像那样使用它

std::cout << Crate();

为了对抗这种情况,我们可以通过const &获得Crate,这将避免复制并允许我们绑定到临时

friend ostream& operator<< (ostream& out, const Crate& c)

学习通常是关于良好的习惯和常识,更不用说你正在写的小例子了。

是的,在您的情况下,性能传递值不会改变任何事情。但有两个问题:

  • 习惯。你应该养成知道如何通过辩论的习惯。如果不需要修改并且不应该移动数据,则通过常量引用传递
  • 按照你写的方式,你的课必须是可复制的。你的是,但情况并非总是如此

至于实际的零作为一个标记,不要为它担心。这毫无意义。