【问题标题】:Why does void setOutputFormat(ostream out, int decimal_places) cause an error?为什么 void setOutputFormat(ostream out, int decimal_places) 会导致错误?
【发布时间】:2011-04-17 06:42:45
【问题描述】:

如果我将其更改为 void setOutputFormat(ostream& out, int decimal_places), 通过引用调用,它可以工作。我不明白为什么? struct和class有什么区别,除了struct成员默认public,class成员默认private?

【问题讨论】:

    标签: c++


    【解决方案1】:

    你说得对,类和结构没有区别,除了默认的私有与私有。

    这里的问题是ostream没有拷贝构造函数,所以不能传值。

    【讨论】:

    • 什么是复制构造函数?对不起,我来自 c#,这对我来说有点倒退
    • @cable729:如果您不知道什么是复制构造函数,那么您正在倒退。我们不能在问答网站上教你 C++。请参阅this 了解下一步该做什么。
    【解决方案2】:

    当您尝试通过 value 传递 ostream 时,您尝试制作流的 副本,这是无效的,因为流对象是 不可复制,也就是说,它们没有定义复制构造函数。但是,当您通过 reference 传递流时,该函数会收到一个可修改的 aliasostream 实例。举个例子:

    void increment(int n) {
        // Increment local copy of value.
        ++n;
    }
    
    int x = 5;
    increment(x);
    // x is still 5.
    

    对比:

    void increment(int& n) {
        // Increment value itself.
        ++n;
    }
    
    int x = 5;
    increment(x);
    // x is now 6.
    

    所以通过引用传递流是唯一有意义的方法,因为您希望setOutputFormat 就地修改原始流。希望这能在一定程度上澄清这个问题。

    【讨论】:

      【解决方案3】:

      正如其他人所说,您正在尝试创建不可复制对象(流)的副本,这会导致该错误。

      在 C++ 中,当您将 var 作为参数传递时,您会复制它(与 C# 相反,在 C# 中,对于引用类型,您总是隐式传递对它的引用)。

      默认情况下,C++ 为每个类提供了一个按位复制构造函数,但这通常不是必需的:例如,考虑一个拥有资源句柄的类:如果你完美地克隆了该类型的对象,你' 将有两个类认为拥有这样的资源,并且两者都会试图在他们破坏时破坏它,这显然不是很好。

      因此,C++ 允许您为每个类提供一个复制构造函数,当必须创建对象的副本时调用该构造函数。由于许多对象(包括流)不需要创建副本(因为它没有意义,因为它不方便或者因为麻烦不值得工作)通常禁用复制构造函数(通过将其标记为privateprotected),并且您不能创建此类对象的副本。

      此外,一般来说,您必须小心对属于复杂类层次结构的对象进行赋值和按值复制,因为您可能会遇到对象切片和其他微妙的问题。实际上,在作为基类的类中阻止复制和赋值是很常见的做法。

      在大多数情况下(包括您的),解决方案是通过引用传递此类对象,从而完全避免复制;请参阅 @Jon Purdy 的答案作为示例。

      顺便说一句,即使是可复制的对象(例如std::strings),最好只传递引用,以避免与复制相关的所有工作;如果您只是为了提高效率而传递引用,但又不想修改对象,最好的解决方案通常是 const 引用。

      C++ 的其他一些地方也使用了副本;我建议你看看 wikipedia page 关于复制构造函数,以更好地理解发生了什么,但是,总的来说,拿起一本 C++ 书并阅读它:C# 在很多方面都与 C++ 不同,并且有有许多虚假的相似之处可能会让您感到困惑。

      【讨论】:

        猜你喜欢
        • 2011-08-31
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-05-04
        • 2020-07-16
        • 2014-06-05
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多