首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

C++构造函数初始化列表 ⑤ ( 匿名对象 生命周期 | 构造函数 不能调用 构造函数 )

, fun 函数 , 调用 Student(18, 180) 代码 , 创建 Student 类型的匿名对象 , 匿名对象的生命周期 只存在于 这一行代码 , 该行代码执行完毕后 , 匿名对象 就会被...二、构造函数 调用 构造函数 ---- 1、构造函数 不能调用 构造函数 构造函数 调用 构造函数 是危险行为 ; 构造函数 调用 构造函数 , 并不会为本对象进行初始化操作 ; 构造函数调用方式..., 天然就会创建一个 匿名对象 , 如果 没有变量 接收 这个 匿名对象 , 该匿名对象 本行表达式执行完毕后 , 就会被销毁 ; 2、代码示例 - 构造函数调用构造函数 下面的代码 , 先定义...执行 Student 的构造函数" << endl; } 然后 , 无参的 构造函数 , 调用 有参构造函数 ; // 构造函数 调用 构造函数 是危险行为 Student() { /...; cout << "执行 Student 的构造函数" << endl; } // 构造函数 调用 构造函数 是危险行为 Student() { // 构造函数调用构造函数

17720

C++不要在构造函数和析构函数调用函数

虽然可以对虚函数进行实调用,但程序员编写虚函数的本意应该是实现动态联编。构造函数调用函数函数的入口地址是在编译时静态确定的,并未实现虚调用。...但是为什么构造函数调用函数,实际上没有发生动态联编呢? 1. 不要在构造函数调用函数的原因 第一个原因,概念上,构造函数的工作是为对象进行初始化。...Visual C++,包含虚函数的类对象的虚指针被安排在对象的起始地址处,并且虚函数表(vtable)的地址是由构造函数写入虚指针的。...2.不要在析构函数调用函数的原因 同样的,析构函数调用函数函数的入口地址也是在编译时静态决定的。也就是说,实现的是实调用而非虚调用。 考察如下例子。...因此,一般情况下,应该避免构造函数和析构函数调用函数,如果一定要这样做,程序猿必须清楚,这是对虚函数调用其实是实调用

2.7K30
您找到你想要的搜索结果了吗?
是的
没有找到

C++核心准则C.82:不要在构造函数或析构函数调用函数

C.82: Don't call virtual functions in constructors and destructors C.82:不要在构造函数或析构函数调用函数 Reason...到目前为止,被调用函数应该只属于构造对象本身,而不是可能存在于派生类的某个覆盖函数。那样做非常难理解。...最坏的情况,构造函数或者析构函数中直接或间接调用一个没有实现的纯虚函数会导致没有定义的行为。...从构造函数和析构函数调用函数并不是本身有什么错误。这种调用的语义是安全的。然而,经验表明这样的调用很少是必须的,很容易扰乱维护者,如果被新手使用会成为错误源。...提示来自构造函数或析构函数的虚函数调用

73450

C++】多态 ⑨ ( vptr 指针初始化问题 | 构造函数 调用函数 - 没有多态效果 )

, 对象 被 创建时 , 由 C++ 编译器 对 对象的 vptr 指针进行初始化操作 , 对象 创建完成 后 , 也就是 虚函数 整理完毕 , 全部放到 虚函数后 , vptr 指针 才会指向... 调用函数 , 则 没有 多态效果 ; 父类 的 构造函数 , 调用了 父类的 虚函数 ; 此时 , 如果 创建 子类对象 , 执行 父类构造函数 , 仍然调用 父类 的虚函数 , 子类的虚函数...没有被调用 , 说明 构造函数 执行期间 , 多态没有生效 ; 参考 【C++】继承 ⑧ ( 继承 + 组合 模式的类对象 构造函数 和 析构函数 调用规则 ) 博客构造函数 调用规则 : 构造函数...调用完毕后 , vptr 指针 才指向 父类的 虚函数表 ; 然后 , 调用 子类 的构造函数 , 此时 子类构造函数 调用 fun 虚函数 , 只能调用 子类本身的 fun 函数 , 此时 vptr..."iostream" using namespace std; // 父类 class Parent { public: Parent() { cout << "调用父类构造函数" << endl

20920

CC++:std::thread构造函数死锁问题:WIN32下不可以DllMain创建线程

最近在设计一个动态库时,全局变量创建了线程,Windows下动态库加载时导致死锁。根本的原因是Windows要求不可以动态库的DllMain函数创建线程,而我的代码结构恰好满足这个条件。...> // 全局变量 A a; // 定义动态库接口函数 extern "C" __declspec(dllexport) void hello() { } 上面的代码A类的构造函数创建了线程,a对象被定义为全局变量...当在动态库执行时,这个a对象的初始化是动态库入口点(DllMain entry point),也就是DllMain函数完成的。...std::thread的构造函数创建新线程,新线程开始执行线程过程之前不能返回。...创建新线程时,开始执行线程过程之前,会以DLL_THREAD_ATTACH方式调用动态库 的入口点(DllMain)1。为此,新线程必须获取加载程序锁。但是当前线程已经持有加载程序锁。

85130

Modern C++ 最核心的变化是什么?

C++ 通过拷贝构造函数和拷贝赋值操作符为类设计了拷贝/复制的概念,但为了实现对资源的移动操作,调用者必须使用先复制、再析构的方式。否则,就需要自己实现移动资源的接口。...name 构造a时,调用了一次字符串的构造函数和一次字符串的移动构造函数。...} 如果函数按值返回,return 语句又直接返回了一个栈上的左值对象(输入参数除外)时,标准要求优先调用移动构造函数,如果不符再调用拷贝构造函数。...v2 = str_split("1,2,3");  注:v 的拷贝构造调用有可能被优化掉,尽管如此语义上仍然是有一次拷贝操作。 同样的代码,支持移动语义的世界里就变得更美好了。...先释放v2原有数据,然后直接从返回值取走数据,然后返回值被析构。 v2 = str_split("1,2,3");  注:v 的移动构造调用有可能被优化掉,尽管如此语义上仍然是有一次移动操作。

95021

深入理解C++的move和forward!

导语 |  C++11标准之前,C++默认的传值类型均为Copy语义,即:不论是指针类型还是值类型,都将会在进行函数调用时被完整的复制一份!对于非指针而言,开销极其巨大!...第一个为显式调用构造函数创建obj时的输出。 后面的输出说明存在三个对象,因此调用了三次析构函数。 即:除了我们显式构造函数之外,我们调用函数、将对象加入vector的时候,也创建了新的对象!...实际上,C++的move函数只是做了类型转换,并不会真正的实现值的移动! 因此,对于自定义的类来说,如果要实现真正意义上的 “移动”,还是要手动重载移动构造函数移动复制函数。...也正因为如此,自己实现移动构造函数的时候,需要将原对象的值手动置为空,以防止同一片内存区域被多次释放!...,另一个调用移动构造函数

1.5K10

c++ lambda内std::move失效问题的思考

博客:www.cyhone.com 公众号:编程沉思录 --- 最近在写C++时,有这样一个代码需求:lambda,将一个捕获参数move给另外一个变量。...这也就意味着,构造vec2时并没有按预期调用移动构造函数,而是调用了拷贝构造函数。 为什么会造成这个问题呢, 我们需要结合std::move和lambda的原理看下。...这是因为std::move配合了移动构造函数使用,本质上是移动构造函数起了作用。...b强制转化了右值引用A&&, 然后触发了移动构造函数移动构造函数,完成了对象b的数据到对象a的移动。...结合本文最初的问题,lambdamove没有生效,显然也是std::move强转的类型不是std::vector&&, 才导致了没有move成功。

3.8K30

理解 C++ 右值引用和 std::move

= test_str_split("1,2,3"); //同样的代码,具备移动语义之后的C++11里 std::vector v1 = test_str_split...+ 上述涉及到的移动语义,是由C++11之前存在的一些历史遗留问题,使C++标准库的实现在多种场景下消除了不必要的额外开销(如std::vector, std::string).这些问题都由于构造函数和拷贝构造函数以及赋值构造函数引起...<<endl; return *this; } /* 3种调用拷贝构造函数的场景 ** 1) 一个对象以值传递的方式传入函数体 ** 2)一个对象以值传递的方式从函数返回 ** 3)一个对象需要通过另一个对象进行初始化...stu2, 调用拷贝构造函数。...+通过拷贝构造函数和拷贝赋值操作符为类设计了拷贝/复制的概念,但为了实现对资源的移动操作,调用者必须使用先复制、再析构的方式。

79630

【Example】C++ 标准库 std::thread 与 std::mutex

使用 thread 默认构造函数创建的 对象不与任何执行线程相关联。 使用 thread 可调用对象构造的 对象将创建一个新的执行线程,并调用的可调用对象 thread。 ...thread::this_thread::get_id、thread::thread::get_id对于默认构造的对象,该方法返回一个对象,该对象的值对于所有默认构造的对象都相同,并且不同于调用时可以联接的任何执行线程返回的值...Args> explicit thread(Fn&& fn, Args&&... args); 初始化构造函数 是 thread(thread&& x) noexcept; 移动构造函数 视情况而定...t4 = std::move(t3); 4,std::thread 的移动构造本身不会对其进行初始化,如果被移动的对象本身是已初始化过的,那么它也是初始化的,反之亦然。...根据 RAII 原则,构造函数中上锁(创建即上锁),析构函数解锁(销毁即解锁)。

1K20

【Example】C++ 标准库多线程同步及数据共享 (std::future 与 std::promise)

(当然你单线程修改也行,但抬杠又有什么意义) 6,std::future 禁用了拷贝构造,但是可以进行移动(move)操作。...2,std::promise 的统一初始化构造 "(p)" 是被禁用的,同时赋值运算符 "operator=" 作用为移动std::promise 不可拷贝,但是可以被引用。...只不过它是用来给异步线程调用的: 成员函数表: 名称 作用 operator= 移动 std::packaged_task 对象,移动! valid() 检查可调用对象是否有效。...额外技术细节请参考 C++ Reference: 函数模板 async 异步地运行函数 f (潜在地可能是线程池一部分的分离线程),并返回最终将保有该函数调用结果的 std::future 。...而是进行惰性求值: async 所返回的 std::future 上首次调用非定时等待函数,将导致在当前线程(不必是最初调用 std::async 的线程),以 args...

1.3K30

C++11——对象移动与右值引用

vector是一个常用的容器了,我们可以很容易的分析这这两次拷贝构造的时机: (1)第一次是函数foo通过临时Obj的对象Obj()构造一个Obj对象并入vector; (2)第二次是通过从函数...由于对象的拷贝构造的开销是非常大的,因此我们想就可能避免他们。其中,第一次拷贝构造vector的特性所决定的,不可避免。但第二次拷贝构造C++ 11就是可以避免的了。...由此可见,右值引用通过移动构造函数移动赋值运算符来实现对象移动C++程序开发的重要性。...同理,如果想以左值来调用移动构造函数构造容器Container的话,那么需要将左值对象通过std::move来获取对其的右值引用,参考如下代码: //紧接上面的main函数的内容 Container...c1=std::move(v); //获取对v的右值引用,然后调用移动构造函数构造c cout<<c1.value<<endl; cout<<v.value<<endl; //v的元素值已经构造函数中被置空

82720

一个C++bug引入的许多知识

接着我们把temp放进了vector,这个时候会调用car的拷贝构造函数,由于car没有定义自己的拷贝构造函数,因此将会执行默认的拷贝构造函数进行浅拷贝操作 这个时候的内存是这个样子 ?...vector发现空间不足时,会在其他地方重新申请一块内存空间,调用原来对象的拷贝构造函数 新的地方进行创建,并把原来地方的对象析构调 第一次循环的时候 vector的大小是1,容量也是1,第二次调用...这样当程序结束调用析构函数的时候,由于vcar[0]和vcar[1]_car指向同一块内存,delete时就会出现问题 问题的根源依旧是没有深拷贝构造函数 四、结论 1、赋值函数,拷贝构造函数,析构函数通常应该被视为一个整体...,即需要析构函数的类也需要赋值函数和拷贝构造函数,反之亦然 2、为了支持快速访问,vector将元素连续储存,当不得不获取新的内存空间的时候,vector会其他地方申请新的空间,并将元素从旧的地方移动到新的地方...,这期间会调用元素的析构函数和拷贝构造函数 3、C++堆内存是可以复用的,当你释放一块内存之后,又立即申请一块内存,新申请的内存空间很可能在刚刚释放的内存上

1.2K90

不知道这些,别说你会C++

它用于显式地表示将资源移动到另一个对象,而不是进行复制。std::move 并不实际移动资源,而只是将左值转换为右值引用,使得移动构造函数移动赋值运算符得以调用。...unsetunset返回值优化unsetunset 返回值优化(Return Value Optimization,RVO)是 C++ 的一种优化技术,用于优化函数返回值的传递过程,避免不必要的复制构造函数调用...函数,当返回一个临时对象时,传统的做法是创建临时对象并返回一个副本给调用者。这意味着会调用一次拷贝构造函数移动构造函数,将临时对象的副本传递给调用者。...然而,通过返回值优化,编译器可以避免创建临时对象的副本,直接将临时对象的值放置调用者的目标对象,从而减少了不必要的构造和析构操作。...如果编译器对返回值进行了优化,则会避免调用拷贝构造函数,而直接在 obj 构造临时对象的值,从而只调用一次构造函数和一次析构函数。 返回值优化是由编译器进行的优化,可以显著提高程序的性能和效率。

10310

现代C++之容器

现代C++之容器 本节将深入学习现代C++实战30讲的第4节与第5节容器所提到的内容。正文中的一些文字直接引用自上面。...不建议接口中使用const string&,除非确知调用者已经持有 string:如果函数里不对字符串做复杂处理的话,使用 const char* 可以避免调用者只有 C 字符串时编译器自动构造 string...2.vector 2.1 异常安全性 vector 通常保证强异常安全性,如果元素类型没有提供一个保证不抛异常的移动构造函数vector 通常会使用拷贝构造函数。...因此,对于拷贝代价较高的自定义元素类型,我们应当定义移动构造函数,并标其为 noexcept,或只容器中放置对象的智能指针。...pop作用是释放元素,c++98设计时还没有移动构造的概念,所以如果返回成员,必须要调用拷贝构造函数,这时分配空间可能出错,导致构造失败,要抛出异常,所以没必要返回成员。

1K10

CC++开发基础——拷贝构造移动构造委托构造

为了避免对象拷贝过程的不必要的复制,拷贝赋值运算符返回类型为引用类型。 拷贝赋值运算符运行结束一般会返回指向该对象的this指针,方便被连续调用。...移动构造函数构造对象的时候避免了拷贝一个新的对象。 移动构造函数可以重复利用原有的内存空间,提供了代码效率。 移动构造函数的形参是(&&)右值引用,而不是(&)左值引用。...当一个对象发生移动以后,不会自主销毁,我们可以移动构造函数的代码逻辑显式地让该对象被析构。...委托构造函数有助于精简函数代码。 委托构造函数对其他构造函数调用的相关代码,不能放在委托构造函数函数体内,必须放在构造函数的初始化列表。...不能在委托构造函数的初始化列表初始化成员变量,会导致代码编译失败。 可以委托构造函数函数设置成员变量的值。

17510

C++11移动语义与右值引用

vector是一个常用的容器了,我们可以很容易的分析这这两次拷贝构造的时机: (1)第一次是函数foo通过临时Obj的对象Obj()构造一个Obj对象并入vector; (2)第二次是通过从函数...由于对象的拷贝构造的开销是非常大的,因此我们想就可能避免他们。其中,第一次拷贝构造vector的特性所决定的,不可避免。但第二次拷贝构造C++ 11就是可以避免的了。...我们可以通过调用C++11标准库中提供的模板函数std::move来获得绑定到左值的右值引用。...由此可见,右值引用通过移动构造函数移动赋值运算符来实现对象移动C++程序开发的重要性。...同理,如果想以左值来调用移动构造函数构造容器Container的话,那么需要将左值对象通过std::move来获取对其的右值引用,参考如下代码: //紧接上面的main函数的内容 Container<

1K20

【Modern C++】深入理解移动语义

但是,移动构造函数可以避免内存重新分配,这是因为移动构造函数的参数是一个右值引用,也可以说是一个临时对象,而临时对象调用之后就被销毁不再被使用,因此,移动构造函数对参数进行移动而不是拷贝。...,那么我们代码通过std::move()调用移动构造或者移动赋值的行为将被转换为调用拷贝构造或者赋值运算符 只有一个类没有显示定义拷贝构造函数、赋值运算符以及析构函数,且类的每个非静态成员都可以移动时...类型转换-move()函数 在前面的文章,我们提到,如果需要调用移动构造函数移动赋值运算符,就需要用到右值。那么,对于一个左值,又如何使用移动语义呢?...push_back(T&&)使用BigObj的移动构造函数将资源从参数移动vector的内部BigObj对象。而在C++11之前,上述代码则生成参数的拷贝,然后调用BigObj的拷贝构造函数。...::vector对应的移动构造不会生成多余的构造,且原本的element都移动到v1;而相比std::array对应的移动构造却有很大的区别,基本上会对每个element都调用移动构造函数而不是对

75610
领券