是否必须通过c ++

时间:2016-04-01 18:28:47

标签: c++ operator-overloading pass-by-reference

我在c ++中有一个中期,我们的一个任务是编写一个类,它会重载<<运算符,以便我们可以将该类的私有字段打印到std::ostream,如下所示: / p>

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编译的,所以我也不能理解它。

请注意,这是电气工程师的课程。

3 个答案:

答案 0 :(得分:5)

在c ++

中通过引用传递类是必须的

没有

&#34;将其作为常量传递给#34;这很愚蠢,如果你按价值传递,那么如果你把参数标记为常量,对外界来说并不重要。

要尽可能直接回答您的问题,按值继承其他类并没有错。当物体较小时,最好通过值传递。在您的情况下,在典型的64位平台上,大小差异为0(每个int 2 * 4bytes vs一个8字节指针)。所以你的&#34; +4字节在堆栈上&#34;实际上并不存在,它的大小相同

我预测优化编译器会重写您的代码以使Crate取值,即使您将其声明为通过引用获取。这将是出于空间局部性和易于访问的原因。如果指针被传递,您需要按照指针来获取数据成员,这会增加一个步骤。

你的教授错误地给你0分,除非在课程中有一些要求非常明确,所有操作员都必须参考参考。 const CrateCrate问题并不重要。

答案 1 :(得分:4)

你不应该收到0,但你也不应该获得全额学分。

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

每次调用它时都会创建一个副本,效率很低。要避免这些副本,您希望通过引用传递,如

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

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

那样使用它
std::cout << Crate();

为了打击我们可以Crate const & friend ostream& operator<< (ostream& out, const Crate& c) ,这将避免复制,并允许我们绑定临时工具

{{1}}

答案 2 :(得分:3)

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

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

  • 习惯。你应该养成知道如何传递你的论点的习惯。如果不需要修改并且不应移动数据,请通过const引用;
  • 你写它的方式,你的班级必须是可复制的。你的是,但情况并非总是如此。

至于实际的零作为标记 - 不要在它上面流汗。什么都没有。

相关问题