C++ inline与operator
title: C++ inline与operator
date: 2020-03-10
categories: c++
tags: [c++]
inline修饰符,operator关键字
1.inline修饰符-内联函数
1.1为何需要inline
在 c/c++ 中,为了解决一些频繁调用的小函数大量消耗栈空间(栈内存)的问题,特别的引入了 inline 修饰符,表示为内联函数。
在系统下,栈空间是有限的,大量调用函数会造成栈溢出
inline char* dbtest(int a) {
return (i % 2 > 0) ? "奇" : "偶";
}
int main()
{
int i = 0;
for (i=1; i < 100; i++) {
printf("i:%d 奇偶性:%s /n", i, dbtest(i));
}
}
每个 for 循环的内部任何调用 dbtest(i) 的地方都换成了 (i%2>0)?"奇":"偶",这样就避免了频繁调用函数对栈内存重复开辟所带来的消耗。
1.2 inline使用限制
inline 的使用是有所限制的,inline 只适合涵数体内代码简单的涵数使用,不能包含复杂的结构控制语句例如 while、switch,并且不能内联函数本身不能是直接递归函数(即,自己内部还调用自己的函数)。
1.3 inline仅是一个对编译器的建议
inline 函数仅仅是一个对编译器的建议,所以最后能否真正内联,看编译器的意思,它如果认为函数不复杂,能在调用点展开,就会真正内联
1.4 建议 inline 函数的定义放在头文件中
因为内联函数要在调用点展开,所以编译器必须随处可见内联函数的定义,要不然就成了非内联函数的调用了。所以,这要求每个调用了内联函数的文件都出现了该内联函数的定义。因此,将内联函数的定义放在头文件里实现是合适的,省却你为每个文件实现一次的麻烦。
1.5 类中的成员函数与inline
定义在类中的成员函数默认都是内联的,如果在类定义时就在类内给出函数定义,那当然最好。如果在类中未给出成员函数定义,而又想内联该函数的话,那在类外要加上 inline,否则就认为不是内联的。
class A
{
public:void Foo(int x, int y) { } // 自动地成为内联函数
}
// 头文件
class A
{
public:
void Foo(int x, int y);
}
// 定义文件
inline void A::Foo(int x, int y){} //注意 A::
1.6 inline 是一种"用于实现的关键字"
关键字 inline 必须与函数定义体放在一起才能使函数成为内联,仅将 inline 放在函数声明前面不起任何作用。
如下风格的函数 Foo 不能成为内联函数:
inline void Foo(int x, int y); // inline 仅与函数声明放在一起
void Foo(int x, int y){}
而如下风格的函数 Foo 则成为内联函数:
void Foo(int x, int y);
inline void Foo(int x, int y) {} // inline 与函数定义体放在一起
1.7 慎用 inline
内联是以代码膨胀(复制)为代价,仅仅省去了函数调用的开销,从而提高函数的执行效率。
如果执行函数体内代码的时间,相比于函数调用的开销较大,那么效率的收获会很少。另一方面,每一处内联函数的调用都要复制代码,将使程序的总代码量增大,消耗更多的内存空间。
以下情况不宜使用内联:
(1)如果函数体内的代码比较长,使用内联将导致内存消耗代价较高。
(2)如果函数体内出现循环,那么执行函数体内代码的时间要比函数调用的开销大。类的构造函数和析构函数容易让人误解成使用内联更有效。要当心构造函数和析构函数可能会隐藏一些行为,如"偷偷地"执行了基类或成员对象的构造函数和析构函数。所以不要随便地将构造函数和析构函数的定义体放在类声明中。一个好的编译器将会根据函数的定义体,自动地取消不值得的内联(这进一步说明了 inline 不应该出现在函数的声明中)。
2 operator
参考:https://blog.csdn.net/liitdar/article/details/80654324
2.1 operator简介
operator 是C++的一个关键字,它和运算符(如=)一起使用,表示一个运算符重载函数,在理解时可将operator和运算符(如operator=)视为一个函数名。
使用operator重载运算符,是C++扩展运算符功能的方法。使用operator扩展运算符功能的原因如下:
使重载后的运算符的使用方法与重载前一致。
扩展运算符的功能只能通过函数的方式实现(实际上,C++中各种“功能”都是由函数实现的)。
2.2 使用operator的原因
对于C++提供的所有操作符,通常只支持对于基本数据类型和标准库中提供的类的操作,而对于用户自己定义的类,如果想要通过该操作符实现一些基本操作(比如比较大小,判断是否相等),就需要用户自己来定义关于这个操作符的具体实现了。
比如,我们要设计一个名为“person”的类,现在要判断person类的两个对象p1和p2是否一样大,我们设计的比较规则是按照其年龄来比较,那么,在设计person类的时候,就可以通过对操作符“”进行重载,来使用操作符“”对对象p1和p2进行比较了(根据前面的分析,实际上比较的内容应该是person类中的数据成员“age”)。
我们上面说的对操作符“”进行重载,说是“重载”,是由于编译器在实现操作符“”功能的时候,已经为我们提供了这个操作符对于一些基本数据类型的操作支持,只不过由于现在该操作符所操作的内容变成了我们自定义的数据类型(如class),而默认情况下,该操作符是不能对我们自定义的class类型进行操作的,所以,就需要我们通过重载该操作符,给出该操作符操作我们自定义的class类型的方法,从而达到使用该操作符对我们自定义的class类型进行运算的目的。
2.3 how
实现一个操作符重载的方式通常分为两种情况:
将操作符重载实现为类的成员函数;
操作符重载实现为非类的成员函数(即全局函数)。
2.3.1 将操作符重载实现为类的成员函数
在类体中声明(定义)需要重载的操作符,声明方式跟普通的成员函数一样,只不过操作符重载函数的名字是“关键字 operator +一个C++预定义的操作符”
bool operator==(const person& ps)const
{
if (this->age == ps.age)
{
return true;
}
return false;
}
class person
{
private:
int age;
public:
person(int nAge)
{
this->age = nAge;
}
bool operator==(const person& ps)const
{
if (this->age == ps.age)
{
return true;
}
return false;
}
};
通过inline和const的学习,建议改成
class person{
private:
int age;
public:
person(int a){
this->age=a;
}
inline bool operator == (const person &ps) const;
};
// 实现
inline bool person::operator==(const person &ps) const
{
if (this->age==ps.age)
return true;
return false;
}
person p1(10);
person p2(10);
if (p1 == p2)
2.3.2 操作符重载实现为非类的成员函数(即全局函数)
对于全局重载操作符,代表左操作数的参数必须被显式指定。
class person
{
public:
int age;
};
// 左操作数的类型必须被显式指定
// 此处指定的类型为person类
bool operator==(person const& p1 ,person const& p2)
{
if (p1.age == p2.age)
{
return true;
}
else
{
return false;
}
}
int main()
{
person p1;
person p2;
p1.age = 18;
p2.age = 18;
if (p1 == p2)
{
cout << "p1 is equal with p2." << endl;
}
else
{
cout << "p1 is NOT equal with p2." << endl;
}
return 0;
}
2.3.4 操作符重载的方式选择
如果一个重载操作符是类成员,那么只有当与它一起使用的左操作数是该类的对象时,该操作符才会被调用;而如果该操作符的左操作数确定为其他的类型,则操作符必须被重载为全局函数;
C++要求'='、'[]'、'()'、'->'操作符必须被定义为类的成员操作符,把这些操作符通过全局函数进行重载时会出现编译错误
如果有一个操作数是类类型(如string类),那么对于对称操作符(比如==操作符),最好通过全局函数的方式进行重载。
2.3.5 操作符重载的限制
实现操作符重载时,需要注意:
重载后操作符的操作数至少有一个是用户定义类型;
不能违反原来操作数的语法规则;
不能创建新的操作符;
不能重载的操作符包括(以空格分隔):sizeof . .* :: ?: RTTI类型运算符
=、()、[]、以及 ->操作符只能被类的成员函数重载
(1) 只有C++预定义的操作符集中的操作符才可以被重载;
(2)对于内置类型的操作符,它的预定义不能被改变,应不能为内置类型重载操作符,如,不能改变int型的操作符+的含义;
(3) 也不能为内置的数据类型定义其它的操作符;
(4) 只能重载类类型或枚举类型的操作符;
(5) 重载操作符不能改变它们的操作符优先级;
(6) 重载操作符不能改变操作数的个数;
(7) 除了对( )操作符外,对其他重载操作符提供缺省实参都是非法的;
最后https://www.cnblogs.com/ZY-Dream/p/10068993.html 这里更详细
https://blog.csdn.net/liitdar/article/details/80656156 operator=
C++ inline与operator的更多相关文章
- [原] inline operator delete & DLL boundary
很久以前写在百度空间的这篇文章: [百度空间] [原] 全局operator delete重载到DLL 首先,纠正一个词“重载”,operator new/delete是替换(replacement) ...
- [c++] Operator overloading
c++的操蛋属性:自己为一档,空一档,其他随意. UB_stack a; UB_stack b = a; // copy auto c = a; auto d {a}; // (or auto d = ...
- C++重载operator的示例
#include<iostream>#include<vector>using namespace std; class test{public: int v; / ...
- operator new与new operator的区别
原文地址:http://www.cnblogs.com/jamesmile/archive/2010/04/17/1714311.html,在此感谢 C++中的operator new与new ope ...
- [百度空间] [原] 全局operator delete重载到DLL
由于很久没有搞内存管理了,很多细节都忘记了今天项目要用到operator delete重载到DLL,发现了问题,网上搜索以后,再对比以前写的代码,发现了问题:原来MSVC默认的operator new ...
- [019]转--C++ operator关键字(重载操作符)
原博客:http://www.cnblogs.com/speedmancs/archive/2011/06/09/2076873.html operator是C++的关键字,它和运算符一起使用,表示一 ...
- [置顶] operator overloading(操作符重载,运算符重载)运算符重载,浅拷贝(logical copy) ,vs, 深拷贝(physical copy)
operator overloading(操作符重载,运算符重载) 所谓重载就是重新赋予新的意义,之前我们已经学过函数重载,函数重载的要求是函数名相同,函数的参数列表不同(个数或者参数类型).操作符重 ...
- C++ operator关键字(重载操作符)(转)
operator是C++的关键字,它和运算符一起使用,表示一个运算符函数,理解时应将operator=整体上视为一个函数名. 这是C++扩展运算符功能的方法,虽然样子古怪,但也可以理解:一方面要使运算 ...
- 重载operator new实现检测内存泄漏是否可行
行与不行,就凭我这水平,说出来未免显示太过自大.不还,我还想根据自己的代码来讨论这个问题. 重载operator new来检测内存只的办法,那就是在new的时候记录指针地址及文件名.行号,在delet ...
随机推荐
- 使用 TensorBoard 可视化模型、数据和训练
使用 TensorBoard 可视化模型.数据和训练 在 60 Minutes Blitz 中,我们展示了如何加载数据,并把数据送到我们继承 nn.Module 类的模型,在训练数据上训练模型,并在测 ...
- EntityFramework Core如何映射动态模型?
前言 本文我们来探讨下映射动态模型的几种方式,相信一部分童鞋项目有这样的需求,比如每天/每小时等生成一张表,此种动态模型映射非常常见,经我摸索,这里给出每一步详细思路,希望能帮助到没有任何头绪的童鞋, ...
- python3多进程 进程池 协程并发
一.进程 我们电脑的应用程序,都是进程,进程是资源分配的单位.进程切换需要的资源最大,效率低. 进程之间相互独立 cpu密集的时候适合用多进程 #多 ...
- QQ好友状态,QQ群友状态,究竟是推还是拉? 网页端收消息,究竟是推还是拉?
https://mp.weixin.qq.com/s/KB1zdKcsh4PXXuJh4xb_Zw 网页端收消息,究竟是推还是拉? 原创 58沈剑 架构师之路 2020-12-28 https:/ ...
- Building a Robust Live Reloader with WebSockets and Go — Brandur Leach https://brandur.org/live-reload
Building a Robust Live Reloader with WebSockets and Go - Brandur Leach https://brandur.org/live-relo ...
- PostgreSQL创建只读权限的用户
1.创建只读角色 CREATE ROLE readaccess; 2.授予对现有表的访问权限 GRANT USAGE ON SCHEMA public TO readaccess; GRANT SEL ...
- LOJ10074架设电话线
USACO 2008 Jan. Silver 在郊区有 N 座通信基站,P 条双向电缆,第 i 条电缆连接基站 Ai 和 Bi.特别地,1 号基站是通信公司的总站,N 号基站位于一座农场中.现在, ...
- C# 实现一个基于值相等性比较的字典
C# 实现一个基于值相等性比较的字典 Intro 今天在项目里遇到一个需求,大概是这样的我要比较两个 JSON 字符串是不是相等,JSON 字符串其实是一个 Dictionary<string, ...
- Kubernetes --(k8s)Job、CronJob
Job https://www.kubernetes.org.cn/job https://www.kubernetes.org.cn/cronjob Job负责批量处理短暂的一次性任务 (short ...
- Java开发中POJO和JSON互转时如何忽略隐藏字段
1. 前言 在Java开发中有时候某些敏感信息我们需要屏蔽掉,不能被消费这些数据的客户端知道.通常情况下我们会将其设置为null或者空字符 "",其实还有其它办法,如果你使用了Ja ...