如何将对象传递给C ++中的函数?

我是C ++编程新手,但我有Java经验。 我需要指导如何将对象传递给C ++中的函数。

我是否需要传递指针,引用或非指针和非引用值? 我记得在Java中没有这样的问题,因为我们只传递了保存对象引用的变量。

如果你还可以解释在哪里使用这些选项,那将是非常好的。


经验法则C ++ 11:

按价值传递,除了何时

  • 你不需要拥有该对象的所有权,并且一个简单的别名会做,在这种情况下,你通过const引用传递
  • 你必须改变对象,在这种情况下,使用const左值引用传递
  • 您将派生类的对象作为基类传递,在这种情况下,您需要通过引用传递 。 (使用先前的规则来确定是否通过const引用传递。)
  • 几乎从不建议通过指针。 可选参数最好用boost::optional表示,并且通过引用可以很好boost::optional别名。

    即使对于复杂对象,C ++ 11的移动语义也使得传值和返回值更具吸引力。


    C ++ 03的经验法则:

    通过const引用传递参数,除了when

  • 它们将在函数内部进行更改,并且这些更改应该反映在外部,在这种情况下,您将传递非const
  • 该函数应该可以在没有任何参数的情况下调用,在这种情况下,您通过指针传递,以便用户可以传递NULL / 0 / nullptr ; 应用先前的规则来确定是否应该传递一个指向const参数的指针
  • 它们是内置类型,可以通过复制传递
  • 它们将在函数内部进行更改,并且这些更改应该反映在外部,在这种情况下,您可以通过复制进行传递 (另一种方法是按照先前的规则进行传递并在函数内部复制副本)
  • (在这里,“按值传递”称为“通过复制”,因为按值传递总是在C ++中创建一个副本03)


    还有更多,但这些初学者的规则会让你走得很远。


    C ++和Java中的调用约定存在一些差异。 在C ++中,技术上讲只有两种约定:传值和传递引用,一些文献包括第三种传递指针约定(实际上是指针类型的传值)。 最重要的是,您可以将常量添加到参数的类型中,从而增强语义。

    通过参考传递

    按引用传递意味着函数将从概念上接收对象实例,而不是其副本。 该引用在概念上是在调用上下文中使用的对象的别名,并且不能为空。 在函数内执行的所有操作都适用于函数外部的对象。 此惯例在Java或C中不可用

    按值传递(并传递指针)

    编译器将在调用上下文中生成对象的副本,并在该函数内使用该副本。 在函数内部执行的所有操作都是针对副本完成的,而不是外部元素。 这是Java中原始类型的约定。

    它的一个特殊版本是将一个指针(对象的地址)传递给一个函数。 该函数接收指针,并且将应用于指针本身的所有操作应用于副本(指针),另一方面,应用于解除引用的指针的操作将应用于该存储器位置处的对象实例,所以函数可能有副作用。 使用指向该对象的指针传值的效果将允许内部函数修改外部值,就像通过引用传递一样,并且还将允许可选值(传递空指针)。

    这是C语言在函数需要修改外部变量时使用的约定,以及Java中引用类型使用的约定:复制引用,但引用的对象相同:对引用/指针的更改不可见该函数,但改变了指向的内存。

    将等式添加到等式中

    在C ++中,可以在定义变量,指针和不同级别的引用时为对象分配常量。 你可以声明一个变量为常量,你可以声明一个常量实例的引用,并且你可以定义所有指向常量对象的指针,指向可变对象的常量指针和指向常量元素的常量指针。 相反,在Java中,您只能定义一个常量级别(final关键字):变量的类型(基本类型的实例,引用类型的引用),但不能定义对不可变元素的引用(除非类本身是不可变的)。

    这在C ++调用约定中被广泛使用。 当对象很小时,可以按值传递对象。 编译器将生成一个副本,但该副本不是一个昂贵的操作。 对于任何其他类型,如果函数不会更改对象,则可以将引用传递给该类型的常量实例(通常称为常量引用)。 这不会复制该对象,而是将其传递给该函数。 但是同时编译器会保证函数内部的对象没有被改变。

    经验法则

    这是一些基本的规则:

  • 为原始类型优先传递值
  • 对于其他类型,优先使用引用常量引用
  • 如果函数需要修改参数use pass-by-reference
  • 如果参数是可选的,则使用pass-by-pointer(如果不应修改可选值,则为常量)
  • 这些规则还有一些小的偏差,第一个是处理对象的所有权。 当一个对象用new动态分配时,它必须用delete(或其[]版本)解除分配。 负责销毁对象的对象或函数被认为是资源的所有者。 当在一段代码中创建一个动态分配的对象时,所有权被转移到另一个元素上时,通常使用传递指针语义来完成,或者如果可能的话使用智能指针来完成。

    边注

    坚持C ++和Java引用之间差异的重要性是非常重要的。 在C ++中,引用在概念上是对象的实例,而不是它的访问器。 最简单的例子是实现交换功能:

    // C++
    class Type; // defined somewhere before, with the appropriate operations
    void swap( Type & a, Type & b ) {
       Type tmp = a;
       a = b;
       b = tmp;
    }
    int main() {
       Type a, b;
       Type old_a = a, old_b = b;
       swap( a, b );
       assert( a == old_b );
       assert( b == old_a ); 
    }
    

    上面的交换函数通过使用引用来更改它的参数。 Java中最接近的代码:

    public class C {
       // ...
       public static void swap( C a, C b ) {
          C tmp = a;
          a = b;
          b = tmp;
       }
       public static void main( String args[] ) {
          C a = new C();
          C b = new C();
          C old_a = a;
          C old_b = b;
          swap( a, b ); 
          // a and b remain unchanged a==old_a, and b==old_b
       }
    }
    

    Java版本的代码将在内部修改引用的副本,但不会从外部修改实际对象。 Java引用是没有指针算术的C指针,它被值传递给函数。


    有几种情况需要考虑。

    参数修改(“输出”和“输入/输出”参数)

    void modifies(T &param);
    // vs
    void modifies(T *param);
    

    这种情况主要是关于风格的:你想让代码看起来像调用(obj)还是调用(&obj)? 但是,有两点差异很重要:下面是可选的情况,并且您希望在重载操作符时使用引用。

    ...和可选的

    void modifies(T *param=0);  // default value optional, too
    // vs
    void modifies();
    void modifies(T &param);
    

    参数未修改

    void uses(T const &param);
    // vs
    void uses(T param);
    

    这是一个有趣的案例。 经验法则是“便宜复制”类型通过值传递 - 这些通常是小类型(但不总是) - 而其他类型则通过const ref传递。 然而,如果你需要在你的函数中创建一个副本,你应该传递值。 (是的,这暴露了一些实现细节。C'est le C ++。)

    ...和可选的

    void uses(T const *param=0);  // default value optional, too
    // vs
    void uses();
    void uses(T const &param);  // or optional(T param)
    

    这里所有情况之间的差别最小,所以选择哪一个让你的生活变得最简单。

    按值进行Const是一个实现细节

    void f(T);
    void f(T const);
    

    这些声明实际上是完全相同的功能! 当传值时,const纯粹是一个实现细节。 试试看:

    void f(int);
    void f(int const) { /* implements above function, not an overload */ }
    
    typedef void NC(int);       // typedefing function types
    typedef void C(int const);
    
    NC *nc = &f;  // nc is a function pointer
    C *c = nc;    // C and NC are identical types
    
    链接地址: http://www.djcxy.com/p/3527.html

    上一篇: How to pass objects to functions in C++?

    下一篇: What is a smart pointer and when should I use one?