代码之家  ›  专栏  ›  技术社区  ›  Michael Sync

C++中的混淆

  •  5
  • Michael Sync  · 技术社区  · 16 年前

    我对C++非常陌生,我现在正在学习它。我有几个问题。。

    1. 虚空和虚空有什么区别 和 无效剂量(Foo-Foo)?

      在C++中,传递对象是“引用”,但似乎不是C++。

    2. 我正在读的那本书说成员函数通过引用传递隐式参数。。

      有谁能给我一个隐式参数的例子和参考?我知道如果要通过引用传递对象,需要使用&(e、 g.Foo(个人和;(p))C++如何通过引用传递隐含的参数?我读到C++中的隐式参数就像是StrutoCube(String STR):StrMistabVar(STR){}…

    3. 是C++中仅供参考的数组吗?

    4. Foo fInstance公司 在福课上?

    例子:

    class Foo {
    
    public:    
        Foo() { }
    
        Foo(const Foo& f) : fInstance(f) {   }  
    
        Foo fInstance;      
    };
    

    提前谢谢。

    12 回复  |  直到 6 年前
        1
  •  10
  •   Community Mohan Dere    6 年前

    1无效剂量测定法(const Foo&foo)和 void DoSomething(Foo foo) Foo 将按值传递(不是引用)。它将与const+&相同;在参数中,除了编译时没有检查。那么,为什么要使用const+&成为无争议的最佳实践;康斯特呢?

    在C++中,传递对象是“引用”,但似乎不是C++。

    • 如果物体 无法复制,需要通过引用传递
    • 如果物体 是一个基类,您应该通过引用获取它,以便用户可以使用派生类调用您的函数
    • const 对它的引用

    我正在读的那本书说成员函数通过引用传递隐式参数。。

    有谁能给我一个隐式参数的例子和参考?我知道如果要通过引用传递对象,需要使用&(e、 g.Foo(个人和;(p))C++如何通过引用传递隐含的参数?我读到C++中的隐式参数就像是StrutoCube(String STR):StrMistabVar(STR){}…

    通过隐式参数,您应该了解 this

    跟随 Konrad 注:注意 这 本身不是通过引用传递的, 这

    3是C++中仅供参考的数组吗?

    他们不是。您将看到数组元素的更改,但数组(结构)不会更改。

    FredOverflow 他的话,一个例证:

    void fun(int* p, size_t size);
    
    int main(int argc, char* argv[])
    {
      int array[15];
      fun(array, 15);
    }
    

    fun 是的,它可能会改变 array 但不管它的行动是什么, 数组

    因此,要改变 数组 我们需要另一份声明:

    void changer(int*& array, size_t& size);
    

    这样我们就可以同时改变内容和结构(并传回新的大小)。当然,我们只能用动态分配的数组来调用这个函数。

    4为什么我不能在Foo类中使用Foo fInstance?

    福 . 大小 福 1 以便解决。所以,如果 有一个 ,它的大小:)?

    通常的解决方案是使用智能指针:

    class Foo
    {
    public:
    
    private:
      std::unique_ptr<Foo> mInstance;
    };
    

        2
  •  7
  •   Konrad Rudolph    16 年前

    既然有那么多 误解和彻头彻尾的错误答案

    它们之间有什么区别 void DoSomething(const Foo& foo) 和 void DoSomething(Foo foo)?

    正如其他人所说,第二个代码需要一个副本(通常调用 Foo

    其他人已经回答了一些特殊的问题(例如运行时多态性)。这并不能解释为什么它已经成为最佳实践。原因很简单,也很难看:因为它是 效率更高。想象一下,将一个向量或字符串传递给另一个方法,或者基本上只是传递给任何大数据结构。复制这种方法的成本通常是巨大的,而且方法可能经常在代码中被调用事实上,方法是 经常调用,否则代码设计得很糟糕。

    另一方面,当你把物体作为 const 总是

    我认为这本书错了。类的成员函数隐式地传递 this 指向当前对象的指针。然而,这是一个 指针

    数组在C++中很少被传递,它们通常作为指针传递:

    void foo(int[] x) { … }
    

    实际上和

    void foo(int* x) { … }
    

    x foo(x) 将成为 foo(&x[0]) .

    可以

    void foo(int (&x)[4]);
    

    但你又一次 明确地

        3
  •  4
  •   Konrad Rudolph    16 年前

    在C++中,传递对象是“引用”,但似乎不是C++。

    不,这是错误的,这是一个普遍的误解。在C#、VB和Java等语言中,变量总是按值传递(异常显式传递为 ref ByRef 在VB中)。

    与C++的区别在于变量不包含类对象本身,它们只包含引用。所以传递给方法的不是对象本身,而是它的引用(但是 按值传递)。

    区别是相当重要的。如果使用C#通过引用传递,则以下代码将打印不同的结果:

    void foo(string s) {
        s = "world";
    }
    
    string s = "hello";
    foo(s);
    Console.WriteLine(s); // prints "hello"
    
        4
  •  4
  •   fredoverflow    16 年前

    因为从概念上讲,Foo的对象需要无限的空间。从技术上讲,Foo类型在Foo的定义中是不完整的。

    您可能需要的是一个指向Foo作为成员的指针。

        5
  •  1
  •   R Samuel Klatchko    16 年前

    void DoSomething(const Foo& foo) void DoSomething(Foo foo) 第一个通过引用传递参数,第二个通过值传递。实际差异是:

    1. 效率。按值传递可能需要调用复制构造函数。如果复制构造函数很昂贵,传递值将增加更多开销。
    2. 语义学。当通过引用传递时,您不知道对象可能被引用。如果基础对象由于其他原因而更改,则引用的值将更改。

    为了更好地解释#3,请考虑以下情况:

    std::string global_string;
    
    void foo(const std::string &str)
    {
        if (str.empty())
        {
            global_string = "whatever";
            // is str still empty??
        }
    }
    

    如果foo被称为 foo(global_string) ,那么当你改变 global_string 这也改变了 str .

        6
  •  1
  •   Yuval Adam    16 年前

    一次一个:

    1. doStuff(Foo f) 意味着一个新的 Foo 当方法被调用-AKA时,对象将在堆栈上创建 按价值 . 打电话 doStuff(const Foo &f) 意味着你只是传递了一个新的引用,对象没有被复制,你只持有一个对它的引用。这是传递参数最安全的方法,因为它不涉及复制对象的副本。这叫做传球 参照 是最接近Java/C的行为。

    2. 同样,数组(假设是 std::array s) 可以通过值、指针或引用传递-没有单一行为。正如Konard提到的,C风格的数组(只不过是内存块) 不能

        7
  •  0
  •   Stack Overflow is garbage    16 年前

    按常量引用而不是按值传递是不太被接受的“好做法”。

    This blog post

    人们倾向于认为const引用更快,但事实是编译器在传递值时可以优化掉副本,因此传递值是一个很好的默认值(实际上,标准库通常会这样做)。例如, std::for_each 和一个函子 )

    不能 逻辑上可以复制。假设对象代表一个窗口。您不希望仅仅因为将window对象传递给另一个函数而在屏幕上显示第二个窗口,从而隐式地创建了一个副本。

    通过引用传递的另一个原因(const或其他)可能是使用多态对象。假设你有一个基类 B D . 可以将D类型的对象作为 const B& 安全地,但将其作为类型的对象按值传递 B 引入切片的风险(仅限于 B 复制子对象,而不是整个对象 D 对象)。

    默认情况下 ,但通过常量引用当然也有它的位置。这两种语言都是有原因的。

        8
  •  0
  •   AndersK    16 年前
      What is the differences between void DoSomething(const Foo& foo) and
    

    无效剂量(Foo-Foo)?

    实用主义上没有区别,const将阻止您更改'foo'的内容,而传递值也不会影响参数的内容,但是就有效性而言,const foo&foo更有效,因为当对象传递给方法时,它不会创建副本。

        9
  •  0
  •   LmSNe    16 年前

    我正在读的那本书说成员函数通过引用传递隐式参数。。

    这

    class FOO{
     int x;
     void doSomthing(int x);
    }
    
    void FOO::doSomething(int x){
      x = x;
    }
    

    会被编译成这样的东西

    void FOO::doSomething(FOO* this, int x){
      this->x = x;
    }
    

        10
  •  0
  •   stinky472    16 年前

    虚空和虚空有什么区别 剂量测定法(Foo-Foo)?

    从广义上讲,后者将 正在传递的参数(换句话说,它是原始Foo对象的副本)。前者将成为 浅拷贝 正在传递的参数(将其地址复制到不可变的常量引用,而不是复制实际的Foo对象)。

    这两个版本都可以访问正在传递的Foo对象的成员。它们都不会修改调用者中的Foo对象。如果函数没有 需要 深度复制是指前者效率更高,因为它避免了深度复制的需要。

    在参数化的一元构造函数(接受一个参数的构造函数)的上下文中,它们可以是隐式的(默认值)或显式的。

    class Foo
    {
        Foo(int x) {...}
    };
    

    这是含蓄的。它允许我们编写如下代码:

    Foo foo = 123;
    
    void f(const Foo& x);
    f(123);
    

    虽然这是明确的:

    class Foo
    {
        explicit Foo(int x) {...}
    };
    

    ... 也不会修改前一个代码。以前的代码必须相应地修改:

    Foo foo(123);
    
    void f(const Foo& x);
    f(Foo(123) );
    

    这通常是一个好习惯,使这样的构造函数显式,除了复制构造函数,我将不进入这里,因为这是相当复杂的。

    C++中的引用?

    我不太清楚这里要问什么,但是数组不能按值传递,如果这是您的意思的话。我们只能将引用/指针传递给数组:

    // takes an array of 10 integers
    void fn(int(&some_array)[10]);
    
    // takes a pointer to an int array
    void fn(int* some_array);
    
    // takes a pointer to an int array (the 10 
    // literal constant is ignored) and this function
    // can likewise take any pointer to int
    void fn(int some_array[10]);
    

    为什么我不能在Foo中使用Foo fInstance 上课?

    这是无限递归的。Foo存储fInstance,fInstance存储另一个fInstance,依此类推。没有什么可以停止递归,所以您只需要让对象存储对象存储对象存储对象等等,直到内存用完为止。因此,编译器会检测到该条件并予以禁止,因为不会产生任何合法的运行时行为。也没有办法确定Foo的大小-那将是一个无穷大的值。

        11
  •  -1
  •   fingerprint211b    16 年前
    void DoSomething(Foo foo)
    

    void DoSomething(Foo& foo)
    

    传递对foo的引用,因此如果在函数中修改foo,则将修改原始foo。我希望这有道理。

    array[5] = 0;//is the same as :
    *(array+5) = 0; //this
    
        12
  •  -5
  •   Prashant    16 年前

    无效剂量测定法(const Foo&foo)和void DoSomething(foo foo)

    如果Foo是原始数据类型,DoSomething(Foo-Foo)按值传递对象Foo;如果Foo是用户定义的数据类型,则按引用传递对象Foo。但是在第二种情况下,如果您更改foo,它会反射回原始对象,这通常是不需要的。这是通过剂量测量来解决的(const Foo&foo)通过引用传递foo(从而节省了通过值传递的额外内存开销),并且仍然不向DoSomething函数提供对foo的写访问。因此,这是一种最佳做法。

    有人能给我一个样品吗

    成员函数中隐式参数的一个例子是对父对象的引用。 this 函数定义中从未提及,但始终可用。

    不,所有用户定义的对象都是通过引用传递的。