Jenocn
925 字
5 分钟
C++中,值、引用、指针在传递时的注意事项
2019-08-14

借参数传递说说C++中的值、引用、指针, 这是c++必须要掌握的要点,也是C++的一个难点,所以想写下我的理解,说说在赋值和传递时的区别的注意事项.

  • 值,引用,指针
  • *右值引用和移动构造

值,引用,指针#

这里用一个例子

参数传递/返回值#

struct Vec2 {
    float x;
    float y;
};

class A {
public:
    // 值传递
    void setPosition(Vec2 pos); 
    // 引用传递
    void setPosition(const Vec2& pos);
    // 指针传递
    void setPosition(const Vec2* pos); 

    // 返回值对象
    Vec2 getPosition() const; 
    // 返回引用对象
    const Vec2& getPosition() const; 
    // 返回指针对象
    const Vec2* getPosition() const; 
};

三种方式的区别:

  • 引用本身占用4个字节
  • 值传递会创建一个临时对象,意味着分配多余的空间
  • 指针可能为空或野指针
  • 加const是防止函数内修改参数对象本身

  值传递会创建一个该类型的临时对象,而引用传递不会创建这个对象,但会创建引用,所以,当传递的值在创建时需要的空间大于4字节的时候,使用值传递就不那么好了,一般情况下,内置的基本数据类型像int,float,char这类,都不用使用引用传递,而直接传值,像自定义的类都推荐使用引用传递.
  至于不使用指针传递,是因为,指针有可能为nullptr类型或者野指针问题,安全性不如引用类型.

  • 返回引用或指针时需要考虑该对象是否被释放

  在返回值中,如果返回的对象不会立即释放,也返回const引用,不过接收返回值的时候,也要使用const引用去接收,这时最容易被忽略的

const auto& retValue = getPosition();

*右值引用和移动构造#

扩展一下,在C++11中,增加了右值引用的概念,右值引用需要结合移动构造来使用

在写一个class的时候,会默认创建一个无参构造函数和一个拷贝构造函数,现在构造函数家族又新增加了一个移动构造函数

  • 右值引用看作是一个服务于参数的特殊引用类型
  • 移动构造必须自行实现
  • 如果没有实现移动构造,右值引用赋值时将视为普通拷贝构造
class A {
public:
    // 构造函数
    A(); 
    // 拷贝构造函数
    A(const A& a); 
    // 移动构造函数
    A(A&& a); 
};

  在stl中有一个方法std::move用于将一个普通类型转换为右值引用,该方法实际上就相当于static_cast<T&&>(value),所以网上常说的,std::move没有move任何东西,它本质上就是做了一个类型转换,将一个普通类型转换为右值引用类型,那么转换为右值引用后该怎么用呢,这就要结合参数了,当你写了一个方法的参数使用了右值引用类型,那么这是就会调用它了,最大的作用目前是在移动构造函数了,所以我理解为,右值引用是一个服务于参数的类型

A value1;
A value2 = std::move(value1); // 将调用移动构造创建这个对象

这个移动构造,最大的用处还是在stl容器的使用上

比如需要转移一个容器内的数据:

std::vector<int> temp { 1, 2, 3 };
/**
    这时,将会调用std::vector的移动构造,
    而实现里面会将temp的指针转移到temp2上,
    而temp将会为空(约定上temp将已经被释放)
*/
auto temp2 = std::move(temp);
C++中,值、引用、指针在传递时的注意事项
https://jenocn.github.io/posts/code/cpp/passingtype/
作者
Jenocn
发布于
2019-08-14
许可协议
CC BY-NC-SA 4.0