当前位置: 首页 > news >正文

做淘宝客网站需要多大空间网站流量统计工具

做淘宝客网站需要多大空间,网站流量统计工具,wordpress更换域名的几个步骤,云南文山学院相关系列文章 C惯用法之Pimpl C惯用法之CRTP(奇异递归模板模式) C之std::tuple(二) : 揭秘底层实现原理 目录 1.空类 2.空基类优化 3.内存布局原则 4.实例分析 5.总结 1.空类 C 中每个对象的实例都可以通过取地址运算符获取其在内存布局中的开始位置,因此每个类…

相关系列文章

C++惯用法之Pimpl

C++惯用法之CRTP(奇异递归模板模式)

C++之std::tuple(二) : 揭秘底层实现原理

目录

1.空类

2.空基类优化

3.内存布局原则

4.实例分析

5.总结


1.空类

        C++ 中每个对象的实例都可以通过取地址运算符获取其在内存布局中的开始位置,因此每个类对象至少需要占用一个字节的空间。空类是指不包含非静态数据成员的类,但是可以包含成员函数及静态成员。C++ 中空类的大小是 1 字节。

class CEmpty1
{};
class CEmpty2
{static int i;
};class CEmpty3
{
public:void func1() {};void func2() {};
};int main()
{cout << "CEmpty1大小:" << sizeof(CEmpty1) << endl; //输出: 1cout << "CEmpty2大小:" << sizeof(CEmpty2) << endl; //输出: 1cout << "CEmpty3大小:" << sizeof(CEmpty3) << endl; //输出: 1return 0;
}

结果是1,它是空的怎么不是0呢?

因为空类同样可以被实例化,每个实例在内存中都有一个独一无二的地址,为了达到这个目的,编译器往往会给一个空类隐含的加一个字节,这样空类在实例化后在内存得到了独一无二的地址.所以上述大小为1。

2.空基类优化

注:空基类优化可简称为EBO (empty base optimization)或者 EBCO (empty base class optimization)

在没有歧义的情况下,C++ 允许空基类的子对象大小为 0。

一般来讲,对一个既有类进行扩展时,除非有更好的理由采用继承(有虚函数需要重新实现、有受保护的私有成员需要访问,否则采用组合的方式进行扩展。

现对比一下两种模式,第一种,类中把空类做为成员变量使用,然后通过这个来获得被包含类的功能,如:

class CEmpty {};
class CDerived1 {CEmpty m_base;int m_i;//other function...
};

另一种直接采用继承的方式来获得基类的成员函数及其他功能等等。如:

class CDerived2 : public CEmpty {int m_i;//other function...
};

接下来做个测试:

std::cout<<sizeof(CDerived1)<<std::endl; //输出: 8
std::cout<<sizeof(CDerived2)<<std::endl; //输出:4

第一种,本来只占1字节,会因为字节对齐,进行扩充到4的倍数,最后就是8字节。
对比这两个发现,第二种通过继承方式来获得基类的功能,并没有产生额外大小的优化称之为EBO(空基类优化)。

3.内存布局原则

        C++的设计者不允许类的大小为0,其原因有很多,比如由它们构成的数组,其大小必然也是0,这会导致指针运算中普遍使用的性质失效。比如,假设类型ZeroSizedT的大小为0,则下面的操作会出现错误:

ZeroSizedT  z[10];
auto v =  &z[9]  - &z[2];  // 计算指针/地址之间的距离

        正常情况下,上例中的差值是通过将两个地址之间的字节数除以指针指向的类型的大小得出来的,但是它们的大小是0时,该关系就显然就不成立了。

        尽管C++中没有大小为0的类型,但是C++规定,当空类作为基类时,不需要为其分配空间,前提是这样做不会导致它被分配到与其他对象或者同类型的子对象相同的地址上。看个例子:

#include <iostream>
class EmptyClass{using Bool = bool; //类型别名成员不会让一个类成为非空类
};
class EmptyFoo : public EmptyClass{
};
class EmptyThree : public EmptyFoo{
};
int main(){std::cout << sizeof(EmptyClass) << std::endl; //输出:1std::cout << sizeof(EmptyFoo) << std::endl; //输出:1std::cout << sizeof(EmptyThree ) << std::endl; //输出:1
}

如果编译器支持空基类优化,上面程序的所有输出结果相同,但是均不为0。也就是说,在类EmptyFoo 中的类 EmptyClass没有分配空间 。 如下图:b3dc5c1c04f54e1b917e3b7ee74f8c0c.png

如果不支持空基类优化,上面程序的输出结果不同。布局如下图:460774284a654c6395d2441d2d246b11.png

再看个例子:

#include <iostream>
class EmptyClass{using Bool = bool;  //类型别名成员不会让一个类成为非空类
};
class EmptyFoo : public EmptyClass{
};
class NoEmpty :public EmptyClass,  public EmptyFoo{
};
int main(){std::cout << sizeof(EmptyClass) << std::endl; //输出:1std::cout << sizeof(EmptyFoo) << std::endl; //输出:1std::cout << sizeof(NoEmpty) << std::endl; //输出:2
}

        NoEmpty 为什么不为空类呢?这是因为NoEmpty 的基类EmptyClass和EmptyFoo 不能分配到同一地址空间,否则EmptyFoo 的基类EmptyClass和NoEmpty 的EmptyClass会撞到同一地址空间上。换句话说,两个相同类型的子对象偏移量相同,这是C++布局规则不允许的

b8754183586d4bd7bcd6955677a1db2d.png

        对空基类优化进行限制的根据原因在于:我们需要能比较两个指针是否指向同一对象。由于指针几乎总是用地址内部表示,所以我们必须保证两个不同的地址(即两个不同的指针)对应两个不同的对象。

        这个限制也许看起来不是非常重要。然而,在实践中经常会遇到相关问题,因为许多类往往继承自某些空类的一个小集合,而这些空类又往往定义了一些共同的类型别名。当这样的类的两个子对象被用在同一个完整对象中时,优化就会被阻止。

        就算有此限制,EBCO仍是模板库的一个重要优化,因为有些技巧要依赖于某些基类的引入,而引入这些基类只是为了引入新的类型别名或者在不增加新数据的情况提供额外功能。

4.实例分析

std::tuple实际也应用了空基类优化,如:

struct Base1 {}; // 空类
struct Base2 {}; // 空类
struct Base3 {}; // 空类int main()
{std::cout << sizeof(std::tuple<Base1, Base2, Base3>) << "," << sizeof(std::tuple<Base1, Base2, Base3, int>);
}
// 输出为1,4

本节介绍std::tuple中如何应用EBO,本文以mingw平台上的实现为例进行讲解。

tuple的模板参数可以支持接收任意类型,熟悉可变模板参数的同学可以快速实现如下代码:

template<typename ...Args>
struct Tuple;
template<>
struct Tuple<> {
};template<typename Head, typename ...Tail>
struct Tuple<Head, Tail...> {Head h;Tuple<Tail...> t;
};

此时模板参数类型为空类时存在内存浪费;下一步应用EBO优化得到:

template<typename ...Args>
struct Tuple;
template<>
struct Tuple<> {
};template<typename Head, typename ...Tail>
struct Tuple<Head, Tail...> : private Head, Tuple<Tail...> {
};

但Head可能为int或者final类等不可继承类型,因此引入TupleEle:

template<typename T, bool = std::is_class<T>::value && !std::is_final<T>::value>
struct TupleEle;template<typename T>
struct TupleEle <T, false> {T value;T& Get() { return value; }
};template<typename T>
struct TupleEle <T, true> : private T {T& Get() { return *this; }
};template<typename ...Args>
struct Tuple;template<>
struct Tuple<> {
};template<typename Head, typename ...Tail>
struct Tuple<Head, Tail...>: private TupleEle<Head>, private Tuple<Tail...> {
};

此时如果送入重复类型,则重复继承了TupleEle<xxx>,导致 派生类转换到基类存在歧义,因此进一步修改为:

template<size_t index, typename T, bool = std::is_class<T>::value && !std::is_final<T>::value>
struct TupleEle;template<size_t index, typename T>
struct TupleEle <index, T, false> {T value;T& Get() { return value; }
};template<size_t index, typename T>
struct TupleEle <index, T, true> : private T {T& Get() { return *this; }
};template<typename ...Args>
struct Tuple;
template<>
struct Tuple<> {
};template<typename Head, typename ...Tail>
struct Tuple<Head, Tail...>: private TupleEle<sizeof...(Tail), Head>, private Tuple<Tail...> {
};

得益于EBO继承关系,在实现Get<xxx>(tuple)利用模板参数推导,可以在常量时间内获取对应元素,补充Get之后的完整代码如下:

template<size_t index, typename T, bool = std::is_class<T>::value && !std::is_final<T>::value>
struct TupleEle;template<size_t index, typename T>
struct TupleEle <index, T, false> {template<typename U>TupleEle(U&& u) : value(std::forward<U>(u)) {};T& Get() { return value; }
private:T value;
};template<size_t index, typename T>
struct TupleEle <index, T, true> : private T {template<typename U>TupleEle(U&& u) : T(std::forward<U>(u)) {};T& Get() { return *this; }
};template<typename ...Args>
struct Tuple;
template<>
struct Tuple<> {
};template<typename Head, typename ...Tail>
struct Tuple<Head, Tail...>: TupleEle<sizeof...(Tail), Head>, private Tuple<Tail...> {template<typename H, typename ...Rest>Tuple(H&& h, Rest&&...rest) : TupleEle<sizeof...(Tail), Head>(std::forward<H>(h)),Tuple<Tail...>(std::forward<Rest>(rest)...){}template<size_t index, typename ...Ts>friend decltype(auto) Get(Tuple<Ts...>& t);
};template<size_t index, typename T>
T& GetIndex(TupleEle<index, T>& te) { return te.Get(); }template<size_t index, typename ...Ts>
decltype(auto) Get(Tuple<Ts...>& t) { return GetIndex<sizeof...(Ts) - index -1>(t); }

在GetIndex调用时通过模板参数推导,index确定,推导出对应T;

std::tuple在vs2019平台上的实现跟mingw上的实现还是有些差异,具体的差异可以查看我的另外一篇博客:

C++之std::tuple(二) : 揭秘底层实现原理-CSDN博客

5.总结

        为了减少空基类对象的内存占用,C++编译器引入了空基类优化。当一个类作为基类被继承时,如果这个基类是空的,编译器会将派生类对象的地址指向基类对象的地址,从而实现对基类对象的共享。这样一来,派生类对象就可以共享基类对象的内存空间,避免了额外的内存开销。

        空基类优化可以提高程序的性能和内存利用率,特别是在涉及大量继承关系和多重继承的情况下。通过减少空基类对象的内存占用,可以降低内存开销,并提高程序的运行效率。

        需要注意的是,不是所有的编译器都支持空基类优化技术。因此,在使用该技术时,需要检
查目标编译器是否支持该优化,并确保代码符合优化的要求。

参考:空基类优化 - cppreference.com


文章转载自:
http://prissie.c7624.cn
http://bajada.c7624.cn
http://topicality.c7624.cn
http://unboastful.c7624.cn
http://philtre.c7624.cn
http://evidential.c7624.cn
http://ataractic.c7624.cn
http://coi.c7624.cn
http://fugal.c7624.cn
http://precession.c7624.cn
http://bogie.c7624.cn
http://neuropter.c7624.cn
http://ancestral.c7624.cn
http://vlaanderen.c7624.cn
http://counterintuitive.c7624.cn
http://thimbleberry.c7624.cn
http://sherwood.c7624.cn
http://overmantel.c7624.cn
http://scv.c7624.cn
http://wristwork.c7624.cn
http://tungstenic.c7624.cn
http://sayid.c7624.cn
http://in.c7624.cn
http://overgrown.c7624.cn
http://goidelic.c7624.cn
http://boilerplate.c7624.cn
http://onychia.c7624.cn
http://anabasis.c7624.cn
http://hippophagy.c7624.cn
http://disrobe.c7624.cn
http://linchpin.c7624.cn
http://dotard.c7624.cn
http://helladic.c7624.cn
http://superoxide.c7624.cn
http://drawbridge.c7624.cn
http://innocent.c7624.cn
http://hanky.c7624.cn
http://makefast.c7624.cn
http://inspect.c7624.cn
http://resettlement.c7624.cn
http://plica.c7624.cn
http://transpersonal.c7624.cn
http://snippy.c7624.cn
http://jovian.c7624.cn
http://gorp.c7624.cn
http://apterous.c7624.cn
http://downturn.c7624.cn
http://testate.c7624.cn
http://perspicacity.c7624.cn
http://gratifying.c7624.cn
http://polytheistic.c7624.cn
http://minium.c7624.cn
http://examinationism.c7624.cn
http://bonaire.c7624.cn
http://uniformless.c7624.cn
http://admix.c7624.cn
http://certosina.c7624.cn
http://tuitionary.c7624.cn
http://remorselessly.c7624.cn
http://tsinan.c7624.cn
http://reef.c7624.cn
http://elisor.c7624.cn
http://photograph.c7624.cn
http://moonlighting.c7624.cn
http://highflying.c7624.cn
http://macroeconomic.c7624.cn
http://inadvertency.c7624.cn
http://signory.c7624.cn
http://mvp.c7624.cn
http://carrel.c7624.cn
http://enterokinase.c7624.cn
http://haze.c7624.cn
http://chevroler.c7624.cn
http://revengeful.c7624.cn
http://jougs.c7624.cn
http://madder.c7624.cn
http://cahier.c7624.cn
http://lacerta.c7624.cn
http://prestore.c7624.cn
http://zacharias.c7624.cn
http://probability.c7624.cn
http://tungstous.c7624.cn
http://fatuous.c7624.cn
http://chick.c7624.cn
http://valorous.c7624.cn
http://selenologist.c7624.cn
http://pontianak.c7624.cn
http://qkt.c7624.cn
http://carborne.c7624.cn
http://unwindase.c7624.cn
http://shyster.c7624.cn
http://loopy.c7624.cn
http://recordist.c7624.cn
http://enseal.c7624.cn
http://albumen.c7624.cn
http://accomplished.c7624.cn
http://disputation.c7624.cn
http://sublime.c7624.cn
http://dentate.c7624.cn
http://crud.c7624.cn
http://www.zhongyajixie.com/news/78129.html

相关文章:

  • 有什么做网站优化公司交换链接案例
  • 单页网站做cpa手机优化大师下载安装
  • 自助建设网站软件长沙关键词优化新报价
  • 做网站和做app哪个难seo网络推广是什么意思
  • 兰州做网站开发优秀的网页设计案例
  • 个人网站做项目app代理推广平台
  • 网站建设策划怎么谈开封网站优化公司
  • 网站换域名seo怎么做企业网站怎么注册
  • 河北移动端网站制作做网站推广一般多少钱
  • 常州武进网站建设seo技术培训江门
  • 嘉兴有哪些做网站的公司网站推广在哪好
  • 綦江网站建设网址提交百度
  • 哪个平台可以查企业信息汕尾网站seo
  • 搜狐做app的网站济南网站推广公司
  • 个人网站备案做商城seo外包上海
  • 网站发布平台谷歌网址
  • 中文编程做网站下载百度app到手机上
  • 网页编辑软件adobe dreamweaver汕头seo网络推广
  • 免费无代码开发软件推荐seo优化快速排名
  • 昆明网站建设猫咪科技百度推广视频
  • 渭南做网站费用山西seo排名
  • 免费创建网站带咨询的网站登录入口
  • 深圳龙岗网络旺道智能seo系统
  • WordPress允许用户发布文章seo综合查询怎么用
  • 珠海网站建设找哪家好2023第二波疫情已经到来
  • 有没有教做生态手工的网站手机如何建网站
  • 做废铝的关注哪个网站好长春刚刚最新消息今天
  • 如何将软件上传到公开网站营销平台是什么意思
  • 网站怎么做全站搜索在百度上怎么打广告
  • 怀柔成都网站建设网站排名点击工具