925 字
5 分钟
C++中,值、引用、指针在传递时的注意事项
借参数传递说说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/