通过引用重载运算符-C++来传递对象
Passing an Object by reference to Overloaded Operator - C++
对C++来说是一个全新的概念。我看到人们通常在运算符重载中通过引用传递对象。嗯,我不知道什么时候真的有必要。在下面的代码中,如果我在对象c1的声明中删除"与",在运算符+中删除c2,我仍然会得到相同的结果。在这种情况下,当我们不想修改c1或c2时,是否有任何理由通过引用?
#include <iostream>
class Keys
{
private:
int m_nKeys;
public:
Keys(int nKeys) { m_nKeys = nKeys; }
friend Keys operator+(const Keys &c1, const Keys &c2);
int GetKeys() { return m_nKeys; }
};
Keys operator+(const Keys &c1, const Keys &c2)
{
return Keys(c1.m_nKeys + c2.m_nKeys);
}
int main()
{
Keys cKeys1(6);
Keys cKeys2(8);
Keys cKeysSum = cKeys1 + cKeys2;
std::cout << "There are " << cKeysSum.GetKeys() << " Keys." << std::endl;
system("PAUSE");
return 0;
}
运算符就像普通函数一样,只是有"花哨"的名称:)
(例如operator+()
而不是sum()
)
因此,应用于函数的参数传递规则也可以应用于重载运算符。
特别是,当您有一个不便宜的参数要复制时(例如,int
、float
是廉价复制参数的示例;std::vector
、std::string
是not廉价复制参数的实例),并且您在方法中观察此参数(即,它是输入只读参数),则可以通过常量引用(const &)
传递它。
通过这种方式,基本上就像原始参数的地址被传递给函数一样,所以不涉及深度复制。深度复制可能非常昂贵,例如,想象一个具有大量元素的向量。
因此,概括一下,当:时,您通过常量引用
- 参数只是不便宜复制(例如,对于int、float等,只是不用担心:传递值很好)
- 在函数/运算符实现中观察到参数(即,它是一个输入只读参数)
如果通过引用传递,则不会生成对象的副本,这对于更复杂的类可以极大地提高性能。
在这种情况下,性能成本可能是微不足道的,可以想象编译器可以完全优化它,但这仍然值得做。稍后,Keys类可能会变为更复杂的类。
通过引用的优点:
- 它允许我们让函数更改参数的值,这有时很有用
- 因为没有生成参数的副本,所以即使与大型结构或类一起使用,它也很快
- 我们可以通过const引用来避免无意的更改
- 我们可以从一个函数返回多个值
参考通过的缺点:
- 因为不能对文字或表达式进行非常量引用,所以引用参数必须是普通变量
- 很难判断通过引用传递的参数是输入、输出还是两者兼有
- 从函数调用中无法判断参数是否会更改。通过值传递的参数和通过引用传递的参数看起来是一样的。我们只能通过查看函数声明来判断参数是通过值传递还是通过引用传递。这可能导致程序员没有意识到函数会改变参数的值
- 由于引用通常由C++使用指针来实现,并且取消引用指针比直接访问指针慢,因此访问通过引用传递的值比访问通过值传递的值慢
您可以阅读以下内容:
http://www.cs.fsu.edu/~myers/c++/notes/references.html
考虑一个long
的vector
,其中有1000万个条目
void foo(vector<long> vl)
{
}
它将导致vector<long>
-的赋值运算符(或复制构造函数),并且需要复制所有10m元素。该临时对象(vl
)的后期析构函数将取消分配内存并执行其他清理操作。它肯定会影响的性能
有一些类,特别是在同步提供程序(关键部分等)周围,还有一些智能指针类,阻止复制构造函数和/或赋值运算符,这样就不会错误地创建赋值或对象。尽管可以实现移动构造函数或移动赋值运算符。
- 什么时候调用组成单元对象的析构函数
- 对RValue对象调用的LValue ref限定成员函数
- CMake-按正确顺序将项目与C运行时对象文件链接
- 空基优化子对象的地址
- 将对象数组的引用传递给函数
- 你能重载对象变量名本身返回的内容吗
- C++使用整数的压缩数组初始化对象
- 找不到成员对象:没有名为get_event()的成员,也处理多态性和向量
- 将对象移动到std::shared_ptr
- 代理对象的常量正确性
- 提升 ASIO 无法识别计时器对象
- 将Ref对象作为类成员
- 将包含C样式数组的对象初始化为成员变量(C++)
- 如何返回一个类的两个对象相加的结果
- 使用std::函数映射对象方法
- 是否需要删除包含对象的"pair"?
- 如何在自删除后将对象设置为nullptr
- 迭代时从向量和内存中删除对象
- 构造对象的歧义
- 使用"std::unordereded_map"映射到"std::list"对象