【C++】简易了解内部类,匿名对象和对象拷贝时的编译器优化
【C++】简易了解内部类,匿名对象和对象拷贝时的编译器优化
内部类:C++内部类是指在一个类的内部定义另一个类。内部类可以访问外部类的私有成员,并且可以用外部类的对象创建内部类的对象。内部类的声明和定义通常在外部类的声明中,但也可以在外部类的定义中进行。内部类的特性:如果⼀个类定义在另⼀个类的内部,这个内部类就叫做内部类。内部类是⼀个独⽴的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限
【C++】简易了解内部类,匿名对象和对象拷贝时的编译器优化
内部类:
C++内部类是指在一个类的内部定义另一个类。内部类可以访问外部类的私有成员,并且可以用外部类的对象创建内部类的对象。内部类的声明和定义通常在外部类的声明中,但也可以在外部类的定义中进行。
内部类的特性:
- 如果⼀个类定义在另⼀个类的内部,这个内部类就叫做内部类。内部类是⼀个独⽴的类,跟定义在全局相比,他只是受外部类类域限制和访问限定符限制,所以外部类定义的对象中不包含内部类。
- 内部类默认是外部类的友元类。
- 内部类本质也是⼀种封装,当A类跟B类紧密关联,A类实现出来主要就是给B类使⽤,那么可以考虑把A类设计为B的内部类,如果放到private/protected位置,那么A类就是B类的专属内部类,其他地方都用不了。
代码示例如下:
代码语言:javascript代码运行次数:0运行复制#include<iostream>
using namespace std;
class A
{
private:
static int _k;
int _h = 1;
public:
class B // B默认就是A的友元
{
public:
void foo(ct A& a)
{
cout << _k << endl; //OK
cout << a._h << endl; //OK
}
};
};
int A::_k = 1;
int main()
{
cout << sizeof(A) << endl;
A::B b;
A aa;
b.foo(aa);
return 0;
}
相应的oj题:
求1+2++...+n_牛客题霸_牛客网
感兴趣的铁子可以试一试哟~
匿名对象:
匿名对象是指在创建对象时不给对象指定一个具体的名字,直接将对象作为表达式的值使用。匿名对象通常在需要临时创建一个对象并使用一次的情况下使用,不需要为其分配内存空间,不需要使用delete来释放内存,由编译器自动回收。
匿名对象的特性:
- 用类型(实参) 定义出来的对象叫做匿名对象,相⽐之前我们定义的 类型 对象名(实参) 定义出来的叫有名对象
- 匿名对象⽣命周期只在当前一行,⼀般临时定义⼀个对象当前用⼀下即可,就可以定义匿名对象。
实现代码如下:
代码语言:javascript代码运行次数:0运行复制class A
{
public:
A(int a = 0)
:_a(a)
{
cout << "A(int a)" << endl;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a;
};
class Solution {
public:
int Sum_Solution(int n) {
//...
return n;
}
};
int main() {
A aa1;
// 不能这么定义对象,因为编译器⽆法识别下⾯是⼀个函数声明,还是对象定义
//A aa1();
// 但是我们可以这么定义匿名对象,匿名对象的特点不⽤取名字,
// 但是他的⽣命周期只有这⼀⾏,我们可以看到下⼀⾏他就会⾃动调⽤析构函数
A();
A(1);
A aa2(2);
// 匿名对象在这样场景下就很好⽤,当然还有⼀些其他使⽤场景,这个我们以后遇到了再说
Solution().Sum_Solution(10);
return 0;
}
对象拷贝时的编译器优化:
- 对象拷贝是指将一个对象的值复制给另一个对象。C++中,默认情况下会进行浅拷贝,即简单地将一个对象的值复制给另一个对象。当类中包含指针等动态内存的成员时,浅拷贝可能会导致多个对象共享同一块内存,当其中一个对象释放内存时,其他对象的指针会变为悬空指针。为了避免这种问题,可以使用深拷贝,即为每个对象分配独立的内存空间,并将原对象的值复制到新的内存空间中。
- 编译器在优化对象的拷贝时,可能会进行一些优化操作,以提高性能和减少内存消耗。例如,编译器可以通过引用计数、写时复制等技术来共享对象,避免不必要的复制。编译器还可以使用移动语义来避免不必要的对象拷贝,将资源所有权从一个对象转移到另一个对象,减少内存的拷贝和分配操作。
特性:
- 现代编译器会为了尽可能提高程序的效率,在不影响正确性的情况下会尽可能减少⼀些传参和传返回值的过程中可以省略的拷贝。
- 如何优化C++标准并没有严格规定,各个编译器会根据情况自行处理。当前主流的相对新⼀点的编译器对于连续⼀个表达式步骤中的连续拷贝会进行合并优化,有些更新更"激进"的编译器还会进行跨行跨表达式的合并优化。
还是来接着看代码吧:
代码语言:javascript代码运行次数:0运行复制 #include<iostream>
using namespace std;
class A
{
public:
A(int a = 0)
:_a1(a)
{
cout << "A(int a)" << endl;
}
A(ct A& aa)
:_a1(aa._a1)
{
cout << "A(ct A& aa)" << endl;
}A& operator=(ct A& aa)
{
cout << "A& operator=(ct A& aa)" << endl;
if (this != &aa)
{
_a1 = aa._a1;
}
return *this;
}
~A()
{
cout << "~A()" << endl;
}
private:
int _a1 = 1;
};
void f1(A aa)
{}
A f2()
{
A aa;
return aa;
}
int main()
{
// 传值传参
A aa1;
f1(aa1);
cout << endl;
// 隐式类型,连续构造+拷⻉构造->优化为直接构造
f1(1);
// ⼀个表达式中,连续构造+拷⻉构造->优化为⼀个构造
f1(A(2));
cout << endl;
cout << "***********************************************" << endl;
// 传值返回
// 返回时⼀个表达式中,连续拷⻉构造+拷⻉构造->优化⼀个拷⻉构造 (vs2019 debug)
// ⼀些编译器会优化得更厉害,进⾏跨⾏合并优化,直接变为构造。(vs2022 debug)
f2();
cout << endl;
// 返回时⼀个表达式中,连续拷⻉构造+拷⻉构造->优化⼀个拷⻉构造 (vs2019 debug)
// ⼀些编译器会优化得更厉害,进⾏跨⾏合并优化,直接变为构造。(vs2022 debug)
A aa2 = f2();
cout << endl;
// ⼀个表达式中,连续拷⻉构造+赋值重载->⽆法优化
aa1 = f2();
cout << endl;
return 0;
}
拷贝编译器会帮我们在底层优化,使得效率更高~
总结:C++内部类可以访问外部类的私有成员,并使用外部类的对象创建内部类的对象。匿名对象是一种临时创建的没有具体名字的对象。编译器在对象拷贝时可能会进行一些优化操作,以提高性能和减少内存消耗。
-------------------------------------------------------End------------------------------------------------------
以上就是我分享的我对【C++】(简易了解内部类,匿名对象和对象拷贝时的编译器优化)理解的相关内容,蟹蟹你的阅读,希望可以对你有所帮助~
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。 原始发表:2025-01-21,如有侵权请联系 cloudcommunity@tencent 删除编译器对象内存优化c++#感谢您对电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格的认可,转载请说明来源于"电脑配置推荐网 - 最新i3 i5 i7组装电脑配置单推荐报价格
上传时间: 2025-07-19 09:22:39
推荐阅读
留言与评论(共有 12 条评论) |
本站网友 词源字典 | 28分钟前 发表 |
当然还有⼀些其他使⽤场景 | |
本站网友 科学的减肥方法 | 9分钟前 发表 |
默认情况下会进行浅拷贝 | |
本站网友 卧室风水知识 | 1分钟前 发表 |
【C++】简易了解内部类 | |
本站网友 私奔 | 10分钟前 发表 |
浅拷贝可能会导致多个对象共享同一块内存 | |
本站网友 儿茶酚胺 | 4分钟前 发表 |
编译器可以通过引用计数 | |
本站网友 双重人格测试 | 14分钟前 发表 |
直接将对象作为表达式的值使用 | |
本站网友 举办培训班 | 1分钟前 发表 |
int Sum_Solution(int n) { //... return n; } }; int main() { A aa1; // 不能这么定义对象 | |
本站网友 失败修复 | 20分钟前 发表 |
本站网友 主流 | 0秒前 发表 |
内部类本质也是⼀种封装 | |
本站网友 商机无限 | 29分钟前 发表 |
所以外部类定义的对象中不包含内部类 | |
本站网友 保护鸟类 | 27分钟前 发表 |
int _a1 = 1; }; void f1(A aa) {} A f2() { A aa; return aa; } int main() { // 传值传参 A aa1; f1(aa1); cout << endl; // 隐式类型 |