@CrazyHenry
2018-02-22T05:40:04.000000Z
字数 4482
阅读 1548
ccccC++Primer
- Author:李英民 | Henry
- E-mail: li
_yingmin@outlookdotcom- Home: https://liyingmin.wixsite.com/henry
快速了解我: About Me
转载请保留上述引用内容,谢谢配合!
class Fuck{public:int a{};//使用1个初始化器,值初始化为0int b{};int c = {6};//等价于c{6},但是不推荐Fuck():a{5}{}//使用1个初始化器,a被值初始化为5,实际这里用()更好,a(5)};int main(){Fuck bitch;cout<<bitch.a<<" "<<bitch.b<<" "<<bitch.c<<endl;unique_ptr<int[]> up(new int[10]{0,5,int(),int(8)});//0,5,0,8//用int{8}也可,建议用int(8)unique_ptr<string[]> up2(new string[10]{"5",string(8,'8'),"Hello"});//10个初始化器,其余被值初始化为空串cout<<up2[1]<<endl;vector<string> vs(9,"Hi");return 0;}
一个初始化器用于创建一个符合=左侧对象类型的对象。初始化器可以完成隐式类型转换("Hello"转换为string("Hello")),值初始化构造函数调用(当没有显示构造,就调用值初始化构造函数),显式构造函数调用如 string(9,'c')!
使用{}就是使用了初始化器。
需要调用单个对象的构造函数的时候,用(),比如:
unique_ptr<string[]> up2(new string[10]{"5",string(8,'8'),"Hello"});//10个初始化器,其余被值初始化为空串//string(8,'8')调用构造函数,不能用string{8,'8'}替代//string s = {'H','i'};是使用类似vector的初始值列表所以,也可以用{}构造一个string对象//new string[10]{"5",string(8,'8'),"Hello"});改为new string[10]{"5",{'8','8','8'...},"Hello"});也等价//但是new string[10]{"5",{8,'8'},"Hello"});的意义就不一样了,编译器会把int型数据8理解为一个字符,和字符'8'一起,用于初始化一个string对象,8对于什么字符呢?
shared_ptr<vector<int>> sp(new vector<int>());//初始化为空的vector<int>
unique_ptr<string[]> up2(new string[10]{"5",string(),"Hello"});//10个初始化器,其余被值初始化为空串
unique_ptr<string[]> up2(new string[10]{"5",string("Hello"),"Hello"});//虽然string{"Hello"}也可以,但是建议使用()
class Fuck{public:int a{};//使用1个初始化器,值初始化为0int b{};int c = {6};//等价于c{6},但是不推荐Fuck():a(5){} //给单个对象初始化的时候,建议还是使用()而不是{}。除了是类内初始值的时候!};
类内初始值以及列表初始化时候,用{}
//类内初始值class Fuck{public:int a{};//使用1个初始化器,值初始化为0int b{};int c = {6};//不好,用int c{6}更大气string s{8,'8'};//error,只能用string s{"88888888"}};
vector<int> vi{1,2,3,4,5};
有时候迫不得已,也只能用{}:
int a{};//值初始化为0,int a()会认为是函数声明class A;A a{};//等价于A a,但是用A a()就会认为是函数声明A a;vector<A> vA{A(),A(args)};//用A()显得比A{}好
赋值是一定有=号的:()和{}只是用于初始化:
int c = {6};//为什么说这句代码显得不大气,就是将赋值和初始化没有搞清楚//{}构造了一个初始化器,将字面值6转换为int对象6,然后赋值给c//显得很多余int c(6);//int型对象c初始化为6
int ds{};//只能这样初始化ds{8};//errords(8);//errords = {8.8};//用8.8构造一个int对象8,赋值给ds
vector<int> vi{};//vi为空vector//等价于vector<int> vi({});//等价于vector<int> vi={};vector<int> vi{1,2,3};//vi初始化为3个元素的vectorstring s{'H','i'};//s初始化为2个元素的vector<char>string s("Hello");//调用构造函数string s{};//一个初始化器,调用默认构造函数构造一个空串,拷贝给s;与string s;等价string as[10]{};//10个初始化器,调用10次默认构造函数,构造10个空串,拷贝给as//可见,数组的空{}和vector<int>的空{}意义是不一样的,虽然都是“数组”,但是vector只构造一个初始化器用于vector对象自身。而数组构建10个初始化器,用于初始化每个元素。//vector<int>的非空{}和数组的{}意义就是一样的了!都用于初始化元素。//数组的{}只用于初始化元素vector<int> vi({1,2,3,5,4});//等价于vector<int> vi{1,2,3,5,4};//等价于vector<int> vi={1,2,3,5,4};
unique_ptr<string[]> up2(new string[10]{"5",string{'8','8'},"Hello"});//10个初始化器,其余被值初始化为空串 。等价于string({'8','8'})cout<<up2[1]<<endl;//输出88
vector<int> vi{};//关于这句代码,总觉得有些别扭,主要在于{}里有值和无值时的动作似乎不一样。//在我看来,vector<int>的构造函数一定是重载了initialization_list的,所以,上面的代码应该进入了这个构造函数。而不像普通的类,默认{}应该用于初始化器,初始化=左侧的对象,比如:class Fuck{public:int a{};//使用1个初始化器,值初始化为0int b{};int c = {6};//不好Fuck():a{5},s(9,'c'){}//使用1个初始化器,a被值初始化为5string s;};int main(){Fuck am{};return 0;}//Fuck没有定义initialization_list的构造函数,但是Fuck am{}默认调用了默认构造函数!//所以我认为,vector<int> vi{}和new vector<int>()应该是调用了不同的构造函数。但结果都是空vector。vector<int> vi{}调用了重载initialization_list的构造函数;vector<int>()调用默认构造函数。//结论:{}对于容器,作用是构建每个元素的初始化器,而不是vector<T>对象本身。//所以,一般直接使用vector<int> vi;//调用默认构造函数,创建空vector
{}有两个功能,其一是初始值列表,其二就是匹配构造函数
#include <iostream>#include <string>#include <vector>#include <iterator>#include <algorithm>#include <typeinfo>#include <numeric>#include <memory>#include <initializer_list>using namespace std;//win+<-/-> 切换窗口位置//ctrl+win+<-/->切换桌面//ctrl+alt+上/下 改变显示器方向class Test{public:Test(initializer_list<int> il):vi(il){cout<<"list cons"<<endl;}vector<int> vi;explicit Test(string s):vi{1,20} {cout<<"string cons"<<endl;}};int main(){Test ta{};//这种空{}优先匹配默认构造函数,默认构造函数可以是explicit的,如果没有默认构造函数,则使用初始值列表构造函数Test tf{1,2,3};//非空优先考虑初始值列表构造函数,如果无法初始化所有成员,则匹配某一构造函数Test tb = {};//拷贝初始化,右侧的{}会优先匹配默认构造函数,但是由于右侧会隐式转换,所以默认构造函数不能是explicit的Test tb2 = {1,2,3};//拷贝初始化,右侧的{}会优先匹配初始值列表构造函数,但是初始值列表构造函数不能是explicit的Test tc({1,2,3});//等价于Test tf{1,2,3};并且初始值列表构造函数可以是explicit的Test td{"Hello"};//优先匹配初始值列表构造函数,如果成员无法转换为int,则匹配构造函数//Test tg({"Hello"});//一定会调用初始值列表构造函数,如果成员无法转换为int,则报错Test ti({});//一定会调用初始值列表构造函数//Test te = {"Hello"};//拷贝初始化,右侧用初始值列表构造函数构造临时量,如果"Hello"不能转换为int,将匹配构造函数(string s),而且(string s)构造函数不能是explicit的return 0;}

class Test{public:Test(initializer_list<int> il):vi(il){cout<<"list cons"<<endl;}vector<int> vi;Test(string s):vi{1,20} {cout<<"string cons"<<endl;}};int main(){Test ta{};Test tf{1,2,3};Test tb = {};Test tc({1,2,3});Test td{"Hello"};//Test tg({"Hello"});Test te = {"Hello"};return 0;}
