1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 游戏开发之拷贝构造函数 即复制构造函数(explicit关键字及拷贝构造函数的调用时机)

游戏开发之拷贝构造函数 即复制构造函数(explicit关键字及拷贝构造函数的调用时机)

时间:2021-05-17 07:43:48

相关推荐

游戏开发之拷贝构造函数 即复制构造函数(explicit关键字及拷贝构造函数的调用时机)

游戏开发之拷贝构造函数,即复制构造函数(explicit关键字及拷贝构造函数的调用时机)(C++基础)

拷贝构造函数是一个特殊的构造函数,是用一个类对象赋值给另外一个类对象时调用。

拷贝构造函数如果没有重写,编译器会自动生成。而重写了拷贝构造函数,编译器不会在生成默认拷贝构造函数,默认构造函数编译器也不会自动生成,需要程序员自己手写。

拷贝构造函数一般用于深拷贝(如果类的内部使用指针则需要重写)。

语法:类名(const 类名& 变量名){函数体}

C++类的构造函数按类型分类:分为普通构造函数拷贝构造函数(复制构造函数)

1.类的拷贝构造函数(复制构造函数)

class A{public://拷贝构造函数 是一个特殊的构造函数/*拷贝构造函数如果没有重写,编译器会自动生成。而重写了拷贝构造函数,编译器不会在生成默认拷贝构造函数,默认构造函数编译器也不会自动生成,需要程序员自己手写。*///用一个类赋值给另外一个类时调用//一般用于深拷贝//如果类的内部使用指针则需要重写//语法:类名(const 类名& 变量名){函数体}int a;A(){std::cout << "调用默认构造函数" << std::endl;_age = 0;}//有参构造函数A(int age) {std::cout << "1个参数" << std::endl;_age = age;}A(const A &a_){std::cout << "调用拷贝构造函数" << std::endl;a = a_.a;_age = a_._age;}void Print() {std::cout << "Age:" << _age << std::endl;}private:int _age;};int main(){A a1;a1.a = 200;A a2(a1);//很像赋值,语义不明确,不推荐使用A a3 = a1;return 0;}

关于使用匿名对象调用拷贝构造函数:

class A{public:int a;A(){std::cout << "调用默认构造函数" << std::endl;_age = 0;}//有参构造函数A(int age) {std::cout << "1个参数" << std::endl;_age = age;}A(const A &a_){std::cout << "调用拷贝构造函数" << std::endl;a = a_.a;_age = a_._age;}void Print() {std::cout << "Age:" << _age << std::endl;}private:int _age;};int main(){//匿名对象:没有名字的对象。//匿名对象:显示调用构造函数A();//匿名对象调用a3实体的拷贝构造函数A a3 = A(300);a3.Print();//匿名对象调用a4实体的拷贝构造函数//注意:使用匿名对象初始化判断哪一个构造函数需要看匿名对象的参数类型A a4(A(400));a4.Print();//此时A(a6) 等价于 A a6A(a6);a6.Print();return 0;}

b 为 A 的实例化对象, A a = A(b) 和 A(b)的区别?

当 A(b) 有实例化对象来接收的时候,那么编译器认为他是一个匿名对象;当没有变量来接的时候,编译器认为你A(b)就等价于A b。

TIPS:不能调用拷贝构造函数初始化匿名对象。

示例如下:

class B {public:B() {std::cout << "默认构造函数!" << std::endl;}B(const B& teacher) {std::cout << "拷贝构造函数!" << std::endl;}public:int mAge;};int main(){B t1;B(t1);//错误,不能用拷贝构造函数初始化一个匿名函数!!return 0;}

2.explicit关键字

explicit用于修饰构造函数,防止隐式转化。

主要是针对单参数的构造函数(或者除了第一个参数外其余参数都有默认值的多参构造)而言。

限制在构造时使用:类对象实体 = 初始化,这种格式进行初始化。

class A{public:explicit A(int a) {std::cout << "构造函数A" << std::endl; }//explict 明确语义,避免二义性A(const A &a_){std::cout << "调用拷贝构造函数" << std::endl;a = a_.a;}};class B{public:B(int a) {std::cout << "构造函数A" << std::endl; }};int main(int argc, char** argv){A a1 = 1; //错误,不允许隐式转换A a2(1); //正确B b1 = 1; //正确B b2(2); //正确A a3;a3.a = 200;A a4(a3);//很像赋值,语义不明确,不推荐使用A a5 = a1;//错误。附加条件explicit,限制条件后,便不允许该种用法return 0;}

3.拷贝构造函数的调用时机

数据结构如下:

class A{public:A(){std::cout << "默认构造函数!" << std::endl;_nAge = 10;}A(int age){std::cout << "有参构造函数!" << std::endl;_nAge = age;}A(const A& person){std::cout << "拷贝构造函数!" << std::endl;_nAge = person._nAge;}~A(){std::cout << "析构函数!" << std::endl;}private:int _nAge;};void test(A p) {}A test2(){A p(10);std::cout << "局部变量p:" << *(int*)&p << std::endl;return p;}void test3(){A p = test2();std::cout << "局部变量p:" << *(int *)&p << std::endl;}

1.旧对象初始化新对象会调用拷贝构造函数

int main(){//1.旧对象初始化新对象A p(10);A p1(p);A P2 = A(p);//相当于A p2(A(p));A p3 = p;//相当于A p3(p);return 0;}

2.函数的形参是普通类对象,实参也是普通的类对象,调用函数会调用拷贝构造函数

int main(){//2.函数的形参是普通类对象,实参也是普通的类对象,调用函数会调用拷贝构造函数A p4(10);test(p4);return 0;}

3.函数返回局部类对象会调用拷贝构造函数

int main(){//3.函数返回局部类对象会调用拷贝构造函数test2();return 0;}

4.函数调用返回局部类对象的函数并初始化另一个类对象

在vs的debug模式下,调用一次拷贝构造函数

在vs的release模式下,不调用拷贝构造函数

int main(){//4.函数调用返回局部类对象的函数并初始化另一个类对象//在vs的debug模式下,调用一次拷贝构造函数//在vs的release模式下,不调用拷贝构造函数test3();return 0;}

TIPS:test3()说明编译器在编译期间会对拷贝构造函数的调用进行优化。

游戏开发之拷贝构造函数 即复制构造函数(explicit关键字及拷贝构造函数的调用时机)(C++基础)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。