我们都知道引用和指针传递是为了避免传参产生临时对象
今天我在温习模板特化的时候发现 引用传参也可能会产生临时对象
所以我较了下面函数传参6种情况
A& const A& A* const A* A*& const A*& 这些情况是否会有临时对象
1.const type*&
#include <iostream>
using namespace std;
class A {
public:
A() {}
A(int v): value(v) {}
~A() {}
bool operator<(const A &other) const //必须加const
{
return this->value < other.value;
}
int value;
};
//当我们需要传递A*时我们也希望能比较大小
bool cmp_(const A *&a, const A *&b)
{
return (*a) < (*b); // 比较指针指向的对象
}
int main()
{
A a = A(10); // 创建对象a
A b = A(20); // 创建对象b
// 调用 cmp_ 函数并输出比较结果
bool result = cmp_(&a, &b);
cout << "Comparison result: " << result << endl;
return 0;
}
我编译一下发现报错了
这里的报错原因是左值引用无法绑定右值
我们知道引用是需要绑定对象的,我们希望它能绑定&a和&b
当引用的对象和实参不同时则会发生类型转换
而这里引用绑定希望绑定一个const A*的的指针 而&a和&b是 A*指针所以在这里生成了一个const A*的临时对象 然后在给形参引用绑定
而临时对象具有常量性,是不可修改的,形参应该改为 const A* const& 声明为指针常量
也就是如下所示
bool cmp_(const A *const &a, const A *const &b) {
return (*a) < (*b); // 比较指针指向的对象
}
2.type*&
我发现只有A*& constA*&会产生临时对象 而且两种产生的原因不同 后者是因为const的问题,而A*&是因为我们传递的&a,&b本身就是右值
当我么尝试用指针先接收&a,&b时再传递时则不会发生问题
#include <iostream>
using namespace std;
class A {
public:
A() {}
A(int v): value(v) {}
~A() {}
bool operator<(const A &other) const {
return this->value < other.value;
}
int value;
};
// 修改 cmp_ 函数,返回的比较结果需要被使用
bool cmp_( A *&a, A *&b) {
return (*a) < (*b); // 比较指针指向的对象
}
int main() {
A a = A(10); // 创建对象a
A b = A(20); // 创建对象b
A *p1 = &a;
A *p2 = &b;
// 调用 cmp_ 函数并输出比较结果
bool result = cmp_(p1, p2);
cout << "Comparison result: " << result << endl;
return 0;
}
3.继承关系下的type*&
如果我们通过传递子类指针给父类指针引用时,是否又可行?
#include <iostream>
using namespace std;
class A {
public:
A() {}
A(int v): value(v) {}
~A() {}
bool operator<(const A &other) const {
return this->value < other.value;
}
int value;
};
class B: public A {
public:
B() {}
B(int v): A(v) {};
~B() {};
};
// 修改 cmp_ 函数,返回的比较结果需要被使用
bool cmp_( A *&a, A *&b) {
return (*a) < (*b); // 比较指针指向的对象
}
int main() {
B a = B(10); // 创建对象a
B b = B(20); // 创建对象b
B *p1 = &a;
B *p2 = &b;
// 调用 cmp_ 函数并输出比较结果
bool result = cmp_(a, b);
cout << "Comparison result: " << result << endl;
return 0;
}
可以发现报错了,这里我们并没有传递右值,但还是产生了临时对象,是因为我们想引用绑定的是父类指针而你传递的是子类指针,所以会发生类型转换产生临时对象后绑定
解决方法:cmp_(A* const& a,A* const& b)继承关系is-a只存在于对象,而指针并没有继承关系所以引用绑定会产生临时对象
所以A&不会产生临时对象,因为子类本生可以看作父类
4. 总结
- 引用绑定类型不匹配或者传入的是一个右值 则会产生临时对象再传给实参
- 当我们需要修改传入的地址时才使用type*&否则使用type*或者type&即可