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

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

我有一个 C++ 期中考试,我们的作业之一是编写一个 class,它重载了 << 运算符,以便我们可以将 class 的私有字段打印到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 而他们传递它参考。

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

我知道 cppreference.com 中提供的示例使用了 const 引用,但是是否有任何严格的规则要求在执行此操作时必须使用 const 引用?

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

我也检查了这两个解决方案的反汇编,但我找不到任何能让我的解决方案值零分的东西。

我也问过我的教授,但他们开始谈论将其作为 const 传递,但我看不出这将如何使这个解决方案在工作/不工作方面变得更好。另一位教授告诉我 "this is syntactically completely incorrect." 但是它是用 Visual Studio 和 MinGW 编译的,所以我也无法理解。

另请注意,这是一门面向电气工程师的课程。

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

没有

"Passing it as const" 太傻了,如果你按值传递,那么你将参数标记为 const 对外界来说并不重要。

尽量直接回答你的问题,按值取另一个class没有错。当对象较小时,最好按值传递。在您的情况下,典型 64 位平台上的大小差异为 0(每个 int 2 * 4 字节与一个 8 字节指针)。所以你的“+4 bytes on the stack”其实是不存在的,大小一样

我预测优化编译器会重写您的代码以按值获取 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)

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

是的,在您的情况下,性能方面的按值传递不会改变任何内容。但这有两个问题:

  • 习惯。你应该养成知道如何表达你的论点的习惯。如果不需要修改且不应该移动数据,则通过const引用传递;
  • 按照你写的方式,你的 class 必须是可复制构造的。你的是,但并非总是如此。

至于作为标记的实际零 - 不要担心。没有任何意义。