C++ 何时使用引用或指针传递参数

C++ 何时使用引用或指针传递参数

C++中,使用引用传递变量有以下原因:

1) 改变调用函数的局部变量: 引用(或指针)允许被调用函数修改调用函数的局部变量。考虑以下示例程序,在这个程序中,fun()可以改变main函数的局部变量x。

C++代码:

#include 
using namespace std;

void fun(int& x) { x = 20; }

int main()
{
    int x = 10;
    fun(x);
    cout << "New value of x is " << x;
    return 0;
}

输出:

New value of x is 20

2)当传递大型参数时: 当传递大型参数时,通过引用(或指针)传递更高效,因为只传递地址,而不是整个对象。考虑以下Employee类和printEmpDetails()函数,该函数打印Employee的详细信息。

C代码

class Employee {
private:
    string name;
    string desig;

    // More attributes and operations
};

void printEmpDetails(Employee emp)
{
    cout << emp.getName();
    cout << emp.getDesig();

    // Print more attributes
}

上面的代码问题是: 每次调用 printEmpDetails () 都会构造一个新的 Employee 对象,这涉及创建所有数据成员的副本。所以更好的实现方式是将 Employee 作为引用传递。

void printEmpDetails(const Employee& emp)
{
    cout << emp.getName();
    cout << emp.getDesig();

    // Print more attributes
}

这仅适用于struct和class变量,因为int、char等基本类型没有效率优势。

3) 避免对象切割: 如果我们将一个子类对象传递给一个期望超类对象的函数,如果通过值传递,传递的对象将被切割。考虑下面的程序,它会打印出”This is Pet Class”。

C代码

#include 

using namespace std;

class Pet {
public:
    virtual string getDescription() const
    {
        return "This is Pet class";
    }
};

class Dog : public Pet {
public:
    virtual string getDescription() const
    {
        return "This is Dog class";
    }
};

void describe(Pet p)
{ // Slices the derived class object
    cout << p.getDescription() << '\n';
}

int main()
{
    Dog d;
    describe(d);
    return 0;
}

输出:

This is Pet Class

在上面的程序中,当我们使用引用传递时,它正确地打印出“ This is Dog Class”。请参见下面修改后的程序。

C++代码

#include 

using namespace std;

class Pet {
public:
    virtual string getDescription() const
    {
        return "This is Pet class";
    }
};

class Dog : public Pet {
public:
    virtual string getDescription() const
    {
        return "This is Dog class";
    }
};

void describe(const Pet& p)
{ // Doesn't slice the derived class object.
    cout << p.getDescription() << '\n';
}

int main()
{
    Dog d;
    describe(d);
    return 0;
}

输出:

This is Dog Class

这对于int、char等基本数据类型也不正确。

4) 在函数中获得运行时多态性: 通过将对象作为引用(或指针)传递给函数,我们可以使其具有多态性。示例,在下面的程序中,print()接收到一个基类对象的引用。如果传递了一个基类对象,函数print()调用基类函数show(),如果传递了一个派生类对象,函数show()被调用。

C++代码

#include 
using namespace std;

class base {
public:
    virtual void show()
    { // Note the virtual keyword here
        cout << "In base\n";
    }
};

class derived : public base {
public:
    void show () { cout << "In derived\n"; }
};

// Since we pass b as reference, we achieve run time
// polymorphism here.
void print (base& b) { b.show(); }

int main(void)
{
    base b;
    derived d;
    print (b);
    print (d);
    return 0;
}

输出:

In base 
In derived 
  • 指针具有值,并且因为C++中默认按值传递函数参数,所以当使用指针时,指针的副本被传递给函数。

结论

如果参数很大(比如一个包含多个字符串的列表),最好使用按引用传递,以避免移动整个字符串。按引用传递实际上只传递参数的地址,而不是参数本身。

Camera课程

Python教程

Java教程

Web教程

数据库教程

图形图像教程

办公软件教程

Linux教程

计算机教程

大数据教程

开发工具教程