那为什么这个东西可以赋值给vector呢? ,大家看红色圈出来的部分,C++11给STL中的这些容器增加了这样一个构造函数。...支持用initializer_list类型的对象去构造vector这些容器。 所以正常使用这个构造应该是这样写: 那我们写成这样 当然也可以,因为构造函数支持隐式类型转换嘛。...它可以在构造函数或函数参数中以列表的形式传递一组值。...可以认为它就是一个常量数组,存储在常量区,initializer_list对象中的元素永远是常量值,我们无法改变initializer_list对象中元素的值。...实际上C++11更新后,容器中增加的新方法最实用的就是插入接口函数的右值引用版本 那关于这里3、4两点提到的右值引用和移动语义我们后面也会花大量篇幅给大家讲解… 8.
其实就是当内置类型使用 { } 初始化时,实际上是在调用它的构造函数进行构造 这就不奇怪了,无非就是让内置类型将 { } 也看做一种特殊的构造:构造 + 赋值 优化为 直接构造 我们可以通过一个简单的...{ 1, 2, 3, 4, 5 }; return 0; } 不止可以初始化五个数,初始化十个乃至一百一千个都是可以的,显然此时的 列表初始化 调用的不是 vector 的构造函数,因为它的构造函数总不可能重载出...所以对于诸如 vector 这种自定义类型来说,需要把 列表初始化 视作一个类型,然后重载对这个类型参数的构造函数就行了,于是 initializer_list 类就诞生了,这是一个模板类,大概长这样... 的构造函数就好了,比如这样 重载了 initializer_list 的构造函数 ---- 位于 vector 类(自己模拟实现的) // 供列表初始化调用 vector(const...简单来说就是 构造即初始化,析构则销毁,利用对象创建时需要调用 构造函数,生命周期结束时会自动调用 析构函数 的特性 智能指针 就是一个对象,一个在构造时申请资源,析构时释放资源的小工具,仅此而已 5.2
例如匿名对象,传值返回的函数调用的返回值等,因为匿名对象在其所在代码行执行完毕后就会被销毁,并且传值返回的函数调用实际利用了中间生成的一个临时变量将返回值从被调用的函数栈帧即将销毁时带出,这个临时变量的值一旦被接收...通过运行结果也可以看出,当wyn::string内部实现了移动构造后,list插入数据时,如果插入数据是右值,在new结点调用struct node结点的构造函数时,会调用string类的移动构造,我们自己实现的...知道上面的知识后,也就能解释为什么移动构造或移动赋值或右值引用版本的插入等等接口的参数都是普通右值引用了,因为这些接口都要对右值进行资源的移动,也就是改变右值引用的引用对象,所以右值引用的时候必须是普通的引用...那如果在函数模板内部,要调用Fun函数呢?我们想保证在调用的时候,依旧可以调用到对应参数类型的函数,也就是保持参数的属性不变。...sort内部进行排序的时候,会依次向后两两比较vector的元素,在比较时就会用我们传的可调用对象进行比较,然后给可调用对象传两个vector元素过去,根据比较结果开始进行排序,所以lambda表达式和仿函数对象一样都是可调用对象
} }; Date d3{ 1,3,2 }; } 对于Date类型,c++11的方式同样调用构造函数。...---- std::initializer_list的使用场景: std::initializer_list一般是作为构造函数的参数,C++11对STL中的不少容器就增加std::initializer_list...作为参数的构造函数,这样初始化容器对象就更方便了。...也可以作为operator=的参数,这样就可以用大括号赋值。因此我们就知道了为什么vector类的空间是如何初始化的,vector的构造函数就存在std::initializer_list的参数。...参数的构造函数 vector(initializer_list il) :_start(nullptr) , _finish(nullptr) , _endofstorage
}; return 0; } vector和list为什么可以这样子初始化,这就要说到一个新的容器了:initializer_list initializer_list 是一个容器,是 C++11...C++11引入initializer_list后才支持的,而这些容器之所以支持使用列表进行初始化,是因为C++11提供了一个构造函数,以initializer_list为参数 看一下C++11vector...的构造: 当用列表对容器进行初始化时,会被认为是initializer_list类型,此时不管有多少个值都能够被初始化vector。...而我们之前自己实现的vector是无法支持的,现在我们可以为之前自己模拟实现的vector提供一个构造函数:遍历initializer_list 中的元素,然后push_back进要初始化的容器当中:...因为array用一个类对数组做了封装,并且在访问array容器中的元素时会进行越界检查:用[]访问元素时采用断言,调用at成员函数访问元素时采用抛出异常检查。
3.initializer_list使用 ★实际编程实践 ” vector v={1,2,3}; // 底层调用vector的构造函数 v={2,5,6}; /.../ 底层调用vector的=操作符 initializer_list ll={4,5,6}; v.insert(v.begin(),ll); // 底层调用下面insert函数 for(auto...x:v) cout<<x<<" "; cout<<endl; vector vv(ll); // 底层调用vector的构造函数 vector city{"Berlin...但是map没有类似的构造,它也应用在map构造函数,insert与=处,跟上面是一样的,都是三处,哈哈~ 使用initializer_list三处: // map构造 map(initializer_list...在初始化的时候,定义及赋值的时候就直接调用构造,后面再次赋值,就是先调用拷贝构造(有可能会被编译器优化),再调用=操作符。
z(0); // 错误 }; 不可拷贝的对象,初始化时不可使用=赋值,但可以使用{}、() std::vector ai1{0}; // 没问题,调用构造函数 std::atomic...另外,在构造函数有参数情况中,若不包含std::initializer_list参数或者 构造未传入实参,()和{}产生一样的效果,否则{}优先匹配std::initializer_list参数的构造函数...w8{std::move(w4)}; // 使用花括号,调用std::initializer_list构造函数 接着上述,在使用{}初始化时,只要参数能强转换为initializer_list...在构造重载匹配中,只要参数能够强转std::initializer_list的T,就会匹配std::initializer_list构造函数,即便有更加匹配的构造函数。...其内部实现尽量不要有修改共享资源的操作(即尽量不要有修改公共变量的操作,否则用锁保护),且内部尽量少的调用其他的函数,因为被调用的函数也可能存在线程不安全的风险。 17.
v2{std::vector{1, 2}}; 在上述代码中v1的值有3个,分别为1 2 3,那么按照该规则,v2的类型岂不是std::vector>,在一开始学习这块的时候...编译器有个特点,对于以花括号初始化的方式则认为是统一初始化,如果构造函数中同样存在std::initializer_list为参数的构造函数,那么则优先调用: class MyClass { public...{ MyClass obj{5, 1.0}; }; 我们可能期望MyClass obj{5, 1.0};调用第一个构造函数(以int和double作为参数的构造函数),但由于存在以std::initializer_list...试想一下,如果不涉及缩小转换(例如,第二个构造函数接受 in std::initializer_list,则代码将使用第二个构造函数(在初始值设定项列表中int 5转换为double 5.0...)默默执行,而开发人员则认为它正在使用第一个构造函数,emm,后果不堪设想~~ 在上面提了,编译器会优先调用参数为std::initializer_list的构造函数,但是有个例外: class MyClass
类型,这是 C++11 新增加的类型,每个容器都增加了使用 initializer_list 的构造函数,数据被识别成 initializer_list 类型后再调用相应的构造函数进行初始化,参考文档:...所以我们如果在以前模拟实现的 vector 中使用 initializer_list 去初始化对象的时候,是会报错的,因为我们以前没有写相应的构造函数,initializer_list 的构造函数也很简单...右值引用和移动语义: 首先我们在 Young::string 中增加移动构造,移动构造本质是将参数右值的资源窃取过来,占位已有,那么就不用做深拷贝了,所以它叫做移动构造,就是窃取别人的资源来构造自己,为什么可以直接窃取别人的资源呢...然后在把这个临时对象做为 Young::to_string 函数调用的返回值赋值给接收的 ret,这里调用的移动赋值。...默认成员函数 原来 C++ 类中,有 6 个默认成员函数: 构造函数 析构函数 拷贝构造函数 拷贝赋值重载 取地址重载 const 取地址重载 最后重要的是前4个,后两个用处不大。
使用场景: std::initializer_list一般是作为构造函数的参数,C++11对STL中的不少容器就增加std::initializer_list作为参数的构造函数,这样初始化容器对象就更方便了...//initializer_list作为vector构造函数的参数 vector(initializer_list l) { _start = new T[l.size...不仅仅有移动构造,还有移动赋值: 在jh::string类中增加移动赋值函数,再去调用jh:to_string(1234),不过这次是将jh::to_string(1234)返回的右值对象赋值给ret1...**然后在把这个临时对象做为jh::to_string函数调用的返回值赋值给ret1,这里调用的移动赋值。...: 然而使用完美转发后: 可以看到最后一次的输出结果不一样,完美转发后完美地保留了对象的原生类型属性 完美转发实际中的使用场景: 如果你使用的函数的是调用其他的函数来实现的,那么你调用的函数也要进行完美转发的修饰
内置类型的默认初始化 Tips:建议初始化每一个内置类型的变量,原因在于定义在函数内部的内置类型变量的值是未定义的,如果试图拷贝或者以其他形式访问此类值是一种错误的编程行为且很难调试。...定义于任何函数体之外的变量会被初始化为0,定义在函数体内部的内置类型变量将不被初始化(uninitialized),一个未被初始化的内置类型变量的值时未定义的,如果试图拷贝或以其他形式访问此类值将引发错误...定义于任何函数体之外的类变量会先进行零初始化再执行默认初始化,定义在函数体内部的类变量会直接执行默认初始化。...class Cat { public: int age; }; int main() { /* 内置类型在函数内部默认初始化, 随机值 */ int int_array[...如果初始化时使用了花括号但是提供的值又无法用来列表初始化,那么就考虑用这些值来调用vector的构造函数了。
相比于 C++98/03,C++11则带来了数量可观的变化,其中包含了约140个新特性,以及对C++03标准中 约600个缺陷的修正,这使得C++11更像是从C++98/03中孕育出的一种新语言。...2 -> 统一的列表初始化 2.1 -> {}初始化 在C++98中,标准允许使用花括号{}对数组或者结构体元素进行统一的列表初始值设定。...fyd p{ 1, 2 }; // C++11中列表初始化也可以适用于new表达式中 int* pa = new int[4]{ 0 }; return 0; } 创建对象时也可以使用列表初始化方式调用构造函数初始化...d1(2024, 4, 1); // C++11支持的列表初始化,这里会调用构造函数初始化 Date d2{ 2024, 4, 2 }; Date d3 = { 2024, 4, 3 };...一般是作为构造函数的参数,C++11对STL中的不少容器就增加 std::initializer_list作为参数的构造函数,这样初始化容器对象就更方便了。
如果没有实现,那么编译器会走initializer_list构造函数图片vector支持initializer_list初始化和赋值的简易代码如下templateclass vector...,每结合一个元素,执行依次循环体,直至容器内的所有元素都被结合完为止.不依赖于下标元素,(通用于stl库的容器)不需要访问迭代器,透明不需要定义处理函数,简洁图片stl库中的一些变化根据C++官网可以查到容器在...(x);//move之后的左值可以右值引用那好端端的有了引用(左值引用),为什么还要在C++11提出右值引用呢?...,但是报错了,原因是此时的捕捉列表捕捉的是父作用域变量值的拷贝,具有常性无法改变且lambda函数总是一个const函数,可以在参数列表后加mutable表示取消参数的常性添加mutable后运行,通过打印查看参数...(部分场景提高效率)包装后明确了可调用对象的返回值和参数类型,更加方便使用。bindstd::bind函数定义在头文件中,是一个函数模板,它就像一个函数包装器(适配器)。
C++11对STL中的不少容器 (vector,list,map…) 就 增加std::initializer_list作为参数的构造函数 ,这样初始化容器对象就更方便了 std::initializer_list...也可以作为operator=的参数 ,这样就可以用大括号赋值 三.对比【C++11特性{ }的隐式类型转换】&【调用initializer_list的vector构造函数】不同原理 C++11中新增的关于...{}用法 (传送门):具体对象是下面代码中Point, 直接调用两个参数的构造 – 隐式类型转换 我们vector容器构造函数的参数是std::initializer_list, 这里是调用initializer_list...的vector构造函数 struct Point { //explicit Point(int x, int y)//调用后,可不让其隐式类型转换 Point(int x, int y)...不同的规则 vector v1 = { 1,2,3,4,3}; // 调用initializer_list的vector构造函数 Point p1 = { 1,1}; // 直接调用两个参数的构造
; int main() { vector arr{1, 2, 3, 4, 5, 6};//这里的初始化为什么可以随意改变元素数量呢?...注意:C++11给右值分为 纯右值(内置类型) 将亡值(自定义类型) 那么在to_string函数中返回了一个将亡值,如果在进行拷贝构造有些没必要: 那么这里在进行拷贝传值的时候就会传给移动构造函数...,移动构造函数内部其实就是交换两个对象的值,反正将亡值也要销毁了,这样就不用进行深拷贝了。...右值 return 0; } 这里只会调用前两个函数,因为func中的参数x都是左值属性,这里就需要一个叫完美转发的在传参的过程中保持了 x 的原生类型属性。...a));//找到之后就将栈中的两个值通过map中储存的包装器中的lamber表达式进行运算,这里要注意数的顺序,先去取出来的在左边,后取出来的在右边 }
: 通过传递两个迭代器来指定要复制的元素范围 ; // 初始化一个 vector 容器 vector vec1 {1, 2, 3}; // 使用 范围构造函数 从 vec1 容器中 复制元素到...vec2 容器 vector vec2(vec1.begin(), vec1.end()); 2、使用 std::initializer_list 初始化列表 初始化 vector 容器 在之前的有参构造函数中...使用 拷贝构造函数 创建 vec3 容器 // 将其初始化为 vec1 的副本 vector vec3(vec1); // 5....; 执行结果 : 二、 vector 容器赋值 vector 容器在初始化时 , 可以设置初始化值 , 在上一个章节中已经进行了讨论 ; vector 容器初始化完毕后 , 要想再 修改 vector...将 vec2 容器中的值替换为 3 个 int 类型数据 8 vector vec2; vec2.assign(3, 8); assign 函数赋值 : 清空容器中的所有元素 , 并用新分配的元素填充容器
在C 语言中,如果函数需要修改变量的值,参数必须为指针,如int foo(int *pval),在 C++ 中,函数还可以声明引用参数int foo(int &val),定义引用参数防止出现 (*pval...2.右值引用 建议:只在定义移动构造函数与移动赋值操作时使用右值引用,区分std::move与std::forward的作用。...因此如果使用非常量的格式化字符串,需要将宏的值而不是宏名插入格式中。使用 PRI* 宏同样可以在 % 后包含长度指示符。...for (int i : {-1,-2,-3}) {} // 在函数调用里用列表初始化。...void TestFunction2(vector v) {} TestFunction2({1,2,3}); 用户自定义类型也可以定义接收 std::initializer_list 的构造函数和赋值运算符
; 4、标准容器的统一初始化 C++11之前初始化一个vector,需要调用多次push_back函数进行初始化。...测试结果.png 6、对象构造的改进 C++11以前类的构造函数不允许调用该类的其它构造函数;每个构造函数都必须自己或者调用一个公共的成员函数来构造类的全部成员.例如: class SomeType1...C++11为这些问题提供了解决方案.C++11允许构造函数调用另一个构造函数(叫做委托构造).这允许构造函数利用其它构造函数的行为而只需增加少量的代码.C#,java和D语言都提供了这种功能....() : SomeType1(42) {} private: int number; }; 注意:这个例子可以通过给new_number设定一个默认参数来达到相同的效果.但是,这种新语法可以让这个默认值在实现中来设置而不是在接口中设置....这带来的一个好处就是,对库代码的维护者而言,在接口中(头文件中)声明默认值,这个默认值被嵌入到了调用端;要改变这个默认值的话,调用端的代码都需要重新编译.但委托构造可以在实现中(CPP文件中)来改变这个默认值
在C 语言中,如果函数需要修改变量的值,参数必须为指针,如int foo(int *pval),在 C++ 中,函数还可以声明引用参数int foo(int &val),定义引用参数防止出现 (*pval...2.右值引用 建议: 只在定义移动构造函数与移动赋值操作时使用右值引用,区分std::move与std::forward的作用。...因此如果使用非常量的格式化字符串,需要将宏的值而不是宏名插入格式中。使用 PRI* 宏同样可以在 % 后包含长度指示符。...for (int i : {-1,-2,-3}) {} // 在函数调用里用列表初始化。...void TestFunction2(vector v) {} TestFunction2({1,2,3}); 用户自定义类型也可以定义接收 std::initializer_list 的构造函数和赋值运算符
Widget w2 = w1;//并非赋值,调用的是复制构造函数 //w1 = w2;//并非赋值,调用的是复制赋值运算符 //普遍性:大括号初始化 //1, STL容器 std::vector<int...复制构造函数 // WidgetBB w6{w444};//大括号,调用的是带有 std::initializer_list型别形参的构造函数,w4的返回值被强制转成成 float,随后 float又被强制转成了... il);//带有形参的构造 }; WidgetA1 ww;//调用的是默认构造 WidgetA1 WWW{};//依然是默认构造 WidgetA1 WWWW();//变成函数的声明了,令人头疼的语法...//如果的确想调用一个带有 std::initializer_list 型别形参的构造函数,并传入一个空的 std::initializer_list的话 //可以通过把空大括号对作为构造函数实参的方式实现这个目的...//如果 processPointer是在 Widget内部得一个成员函数模板,而你想禁止使用 void*指针来调用 //通不过编译得做法 //通不过编译得做法 class Widget{ public
领取专属 10元无门槛券
手把手带您无忧上云