潍坊网站建设公司哪家好,哈尔滨市住房和城乡建设局局网站,wordpress幻灯片设置,重庆专业网站排名团队匿名对象 #x1f4a2;什么是匿名对象#x1f4a2;匿名对象的创建方式及作用域#x1f4a2;匿名对象的对象类型#x1f4a2;#x1f4a2;匿名的基本数据类型对象#x1f4a2;#x1f4a2;匿名的自定义的类类型对象#x1f4a2;#x1f4a2;匿名的标准库的类对象 … 匿名对象 什么是匿名对象匿名对象的创建方式及作用域匿名对象的对象类型匿名的基本数据类型对象匿名的自定义的类类型对象匿名的标准库的类对象 匿名对象的使用方式作为临时值使用可以调用成员赋值和初始化 匿名对象的注意事项权限问题不能取地址缺陷 什么是匿名对象
匿名对象Anonymous Object 是指在创建对象的时候并没有给它命名。它们通常用于在单个语句中执行一系列操作或调用某个函数并且不需要将其结果存储到对象中。
匿名对象的创建方式及作用域
直接在类名后加()当遇到有参或者拷贝构造时需要加上相应的参数。有名对象其生命周期在当前函数局部域。匿名对象其生命周期在当前行。
code:
#include iostream
using namespace std;class Person
{
public:Person(){cout Person默认构造 endl;}Person(string name){cout Person有参构造 endl;m_name name;}Person(const Person per){cout Person拷贝构造 endl;}~Person(){cout 析构析构析构 endl;}void print_info(){cout name: m_name endl;}private:string m_namehuahua;
};int main()
{Person per1; // 有名对象 -- 生命周期在当前函数局部域per1.print_info();Person().print_info(); // Person()匿名对象 -- 生命周期在当前行Person(lili).print_info(); // Person(lili)匿名对象 -- 生命周期在当前行Person(per1).print_info(); // Person(per1)匿名对象 -- 生命周期在当前行system(pause);return 0;
}result:
Person默认构造
name: huahua
Person默认构造
name: huahua
析构析构析构
Person有参构造
name: lili
析构析构析构
Person拷贝构造
name: huahua
析构析构析构这段代码中Person().print_info()Person(“lili”).print_info()Person(per1).print_info()均是匿名对象。 他们只是实例化对象时运行的构造函数不一样。 可以看到当实例化匿名对象的那一行代码执行完之后就执行了析构函数释放对象。 而有名对象是在main函数的作用域等main函数执行完后才会执行析构函数(本案例中看不到 因为最后可看到的的执行结果停留在system(“pause”))这一步。 匿名对象的对象类型
匿名对象的类型可以是基本数据类型如intdouble, char等。匿名对象的类型可以是自定义的类类型。匿名对象的类型可以是标准库中的类类型。
匿名的基本数据类型对象 int(5), double(3.14) char(‘A’)就是在创建匿名对象。 下面代码中的int()int(3)是在创建匿名的int类型对象。 int a int(10)创建匿名对象int(10)并将其赋值给aa就是有名对象。 code:
#include iostream
using namespace std;void test01()
{cout int(): int() endl; // 创建匿名的int类型对象cout int(3): int(3) endl;int a int(10); // 创建匿名int类型对象int(10)赋值给有名的int对象acout int a int(10): a endl;
}
int main()
{test01();system(pause);return 0;
}result:
int(): 0
int(3): 3
int a int(10): 10匿名的自定义的类类型对象 之前代码示例中的如下语句均为创建匿名对象。 Person().print_info(); // Person()匿名对象 – 生命周期在当前行 Person(“lili”).print_info(); // Person(“lili”)匿名对象 – 生命周期在当前行 Person(per1).print_info(); // Person(per1)匿名对象 – 生命周期在当前行 而如下代码是在创建有名对象per1。 Person per1; // 有名对象 – 生命周期在当前函数局部域 匿名的标准库的类对象
#include iostream
#include vector
using namespace std;void print_vector(const vectorint vec)
{for (vectorint::const_iterator it vec.begin(); it vec.end(); it){cout *it ;}cout endl;
}void test01()
{print_vector(vectorint{0, -1, -2}); // 创建匿名对象 vectorint{0, -1, -2}vectorint vect1{1, 2, 3}; // 创建有名对象vect1print_vector(vect1);vectorint vect2 vectorint{ 4, 5, 6 }; // 创建匿名对象vect2print_vector(vect2);
}
int main()
{test01();system(pause);return 0;
}result:
0 -1 -2
1 2 3
4 5 6匿名对象的使用方式
作为临时值使用
#include iostream
using namespace std;void print_info(int a)
{cout a endl;
}int main()
{print_info(3); // 这里的3可以看作是匿名的int对象即int(3)system(pause);return 0;
}result:
3
可以调用成员 之前代码示例中的如下语句中的匿名对象可以调用成员但也只能调用一次后面不会再用到它 所以不需要有有名对象存储。 Person().print_info(); // Person()匿名对象 – 生命周期在当前行 Person(“lili”).print_info(); // Person(“lili”)匿名对象 – 生命周期在当前行 Person(per1).print_info(); // Person(per1)匿名对象 – 生命周期在当前行 赋值和初始化 下面代码中int a Person(“Feifei”, 10).get_age(); 中Person(“Feifei”, 10)是匿名对象它调用了成员函数get_age() 给变量a赋值。 Person per1 Person(“Maomao”, 13); 中Person(“Maomao”, 13)匿名对象配置给有名对象per1。 #include iostream
using namespace std;class Person
{
public:Person(string name, int age) : m_name(name), m_age(age) {}int get_age(){return m_age;}
private:string m_name huahua;int m_age 10;
};int main()
{// Person(Feifei, 10)匿名对象调用其成员函数给其它变量赋值int a Person(Feifei, 10).get_age(); cout a: a endl;// 匿名对象Person(Maomao, 13)可以用于初始化per1对象Person per1 Person(Maomao, 13); system(pause);return 0;
}result:
a:10匿名对象的注意事项
权限问题 下面代码中int a Person(“Feifei”, 10).get_age(); 中Person(“Feifei”, 10)是匿名对象它调用了成员函数get_age() 给变量a赋值。 Person per1 Person(“Maomao”, 13); 中Person(“Maomao”, 13)匿名对象配置给有名对象per1。 #include iostream
using namespace std;class Person
{
public:Person(string name, int age) : m_name(name), m_age(age) {}Person(Person per) : m_name(per.m_name), m_age(per.m_age) {}int get_age(){return m_age;}void set_age(int age){m_age age;}void print_info(){cout name: m_name , age: m_age endl;}
private:string m_name huahua;int m_age 10;
};int main()
{Person per1(Tiantian, 12); // 创建有名对象per1Person per2(per1); // 拷贝构造创建有名对象per2per2.print_info();system(pause);return 0;
}result:
name: Tiantian, age: 12以上代码中先创建有名对象per1然后利用per1创建有名对象per2。代码没有问题。 下面使用匿名函数实现。 #include iostream
using namespace std;class Person
{
public:Person(string name, int age) : m_name(name), m_age(age) {}Person(Person per) : m_name(per.m_name), m_age(per.m_age) {}int get_age(){return m_age;}void set_age(int age){m_age age;}void print_info(){cout name: m_name , age: m_age endl;}
private:string m_name huahua;int m_age 10;
};int main()
{// 想使用Person(Tiantian, 12)匿名对象去利用拷贝构造创建per2对象// 编译会报错,错误 C2558 class“Person” : 没有可用的复制构造函数或复制构造函数声明为“explicit”// 原因就在于这个匿名对象它和临时对象一样是具有常性的而在拷贝构造中接收的是Person per// 用一个非常性的对象去引用常性的就会有问题。编译器会认为是权限放大的问题。Person per2(Person(Tiantian, 12)); per2.print_info();system(pause);return 0;
}以上代码中想使用Person(“Tiantian”, 12)匿名对象去利用拷贝构造创建per2对象。 匿名对象它和临时对象一样是具有常性的而在拷贝构造中接收的是Person per 用一个非常性的对象去引用常性的就会有问题。编译器会认为是权限放大的问题。会报错。 修改方法为Person(Person per) : m_name(per.m_name), m_age(per.m_age) {} 在 Person per前加上const修饰即可。 加上const后实现了权限平移此时既可以接受普通引用也可以接收常引用提高了代码的健壮性。 不能取地址
cout Person(Tiantian, 12) endl; 会报错。
因为匿名对象随时可能被销毁如果取了其地址后续的代码会变得不稳定而且编译器可能会对匿名对象进行优化
如果将其存储于寄存器中就娶不到确定的内存地址。缺陷
调试和维护上的困难无法使用debug模式直接跟踪和check其当前值增加调试难度。 如果频繁的创建和销毁匿名对象会影响性能的开销。