C++Annoatation 02: More extensions to C , Some fea
添加时间:2013-5-21 点击量:
More extensions to C , Some features of C++11
对于稍微有些C++的同窗,可能都知道C++和C的一些首要差别,大的差别就是一个是面向对象,一个是面向过程,这就涉及到对象; 同时,还有定名空间的引入,防止变量名冲突; 还有struct支撑成员函数等。 我就持续注释一些更须要重视的一些不合,一些是C++11中的器材。
引用
可以经由过程引用批改它引的对象,然则不克不及改变它本身。这么听来,就像是常量指针, 别的,引用也让代码加倍天然,不像c里边会呈现一堆的&来默示传址调用。
int a=1;
int &r=a;
int const rr = a; // intconst 和
int&是同一个器材,引用只是一个语法糖。
应用引用时,有几点须要记住:
引用定义时必须初始化! 其实看上方的法度例子就知道, const的器材都必须初始化
不要在函数中返回局部变量的引用
函数中是否应用引用的场合
引用,可以当做函数参数传入,如许就可能会批改所引用对象。指针也能达到如许的目标,如许多几许少会造成一些困惑,我们可以依从一些原则:
若形参是内建类型(int double char等),且我们不须要改变实参值,直接传值调用
若形参时内建类型,且我们须要批改它,那就经由过程指针调用
若形参类型是类,布局体等,我们不须要改变它的成员变量,采取 const &
调用
若形参类型是类等,需要改变,采取引用&调用
应用引用调用,可以或许避免机关函数的调用,节俭开支。
别的,须要实现链式操纵的,返回值选择引用类型,也能避免机关函数的调用。经典例子就是 “cout”
右值引用 (对C++11不是很熟悉,会有一些懂得上的错误,请斧正)
C++11中多了个右值引用。 主如果因为姑且变量(右值)不克不及很好的同 const&
很好的区分隔来,是以C++11多了个右值引用&&。
举例申明下:
int intVa()
{
return 5;
}
int& a = intVal(); // 错误!
引用姑且变量
int const& a = intVal(); //
正确,引用不变姑且变量
int a = &intVal(); // 错误!
intVal()不是左值
我们持续看:
void receive(int& value){++value; cout <<“L-value parameter\n”;} // 左值引用版本
void receive(int&&
value){++value; cout << R-value
parameter\n;} // 右值引用版本
void
receive(int const& value)
{++value; cout << L-value const
parameter\n;} // ++value不克不及有,不然编译错误。这算是右值引用和const&的差别。
如此调用:
int main()
{
receive(18); //
R-value 19
int v = 5;
int const& cri =
v;
receive(cri); // L-value
const
receive(v); // L-value
6
receive(intVal()); // R-value
6
}
若我们把 void receive(int& value)删除,则receive(v) 返回 L-value
const parameter。 函数重载的右值引用版本,仅在匿名变量传入时激发。
别的,右值引用版本函数中,可以对value进行操纵,可以看出,右值引用 用于获取 匿名姑且变量 的 把持权,而 int
const& 版本的却不可。
重视下:
若引入别的个重载版本 void(int value), 那么将产生错误,因为该例中,匿名变量也可以解析成 int
型,导致重载冲突。
别的,右值引用的进阶应用是 是 移动语义 move semantics 和 完美转发 perfect
forwarding 的根蒂根基。移动语义我临时还不懂啥,今后再讲述。
强类型-列举类
C++中,列举类型其实就是int,不合列举类型可以经由过程static_cast<int>
来进行斗劲操纵;别的,不合列举类型的内部值不克不及雷同,因为C++中列举类型的感化局限不被列举名所限,而是受感化域限制。
C++11中,引入了 enum class ,来解决上述题目。
enum class CharEnum: unsigned char //
默认是int,可以经由过程这个“:”符号改变
{
NOT_OK, // 默认 0
OK //
自增1
};
应用时,要参加列举类名与感化域符,即 CharEnum::OK.
前向声明如下
enum Enum1; // Illegal: no size
available
enum Enum2: unsigned int; // Legal in C++11:
explicitly declared type
enum class
Enum3; // Legal in C++11: default int type is
used
enum class Enum4: char; // Legal in C++11:
explicitly declared type
初始化列表
c说话中,可以用大括号包含一个初始化列表来初始化数组、布局体。C++11把这个概念持续扩大了,引入了 initializer_list<Type>
这个模本类,可以扩大初始化类,同时也能对初始化列表进行个性化操纵。 应用前,要包含头文件 <initializer_list>
。同时,可以将初始化列表当做函数形参传入。
void values(initializer_list<int> iniValues)
{
cout << Initializer list having
<< iniValues.size() << values\n;
for
(
initializer_list<int>::const_iterator begin =
iniValues.begin();
begin !=
iniValues.end();
++begin
)
cout << Value: << begin << \n;
}
这个常识点Mark下,今后持续深切懂得,记得在 boost 中如同也有类似的器材。
auto 和 decltype 这个我感觉,好了
因为C++的声明可能会很是错杂难懂,C++11将曾经的auto关键字,使其可以或许主动解析类型,不错,基于boost的改进。
auto 和 decltype
功能异常强大,不过小我认为,还是要把模板常识搞透了再深切应用这个关键字斗劲好,根蒂根基神马的,最首要的了。
int (fun())[10], 默示
fun是个函数,返回一个指向int数组[10]的指针。如许不好懂得,用上auto后,一切这么天然
auto func() -> int()[10];
别的,比如 vector<int>::const_iterator ci = v.begin();
可以改写成 auto ci = v.begin(); 例子很多,信赖auto的应用,会让C++加倍受迎接。
类型定义和 ‘using’ 声明
比如 unsigned long int compute(double, double),
这个函数指针的声明,应用typedef可以变成如许:
typedef unsigned long int(pfun)(double, double);
然则,我们声明时 pfun f;
时,袒护了Pfun实际上是一个指针的事实,必须看typedef定义才知道。关于这点,我很诟病,导致我函数指针一向没学好。C++11中将这点进行了升华,采取using
关键字:
using pfun =
unsigned long int(double, double);
或者和auto共同:
using
pfun = auto (double,double)
-> unsigned long
int;
for轮回的局限操纵
传统C/C++ 的for采取标准的
for(init;cong;next)语句,这对遍历的应用,不那么的便捷,很多说话都供给结局限操纵符,在STL的算法库也包含了for_each办法,然则还是不敷便捷。C++11中引入了for的局限操纵版本:
int array[100];
for (auto &element:array){...}
这里,推荐应用auto,避免思惟肩负在解析类型上。 同时,element是变量名,默示array中每次遍历的元素。
引用操纵符很是首要,若是要批改元素或array是类类型,则用引用; 若是类类型,但不改变,用const&;
通俗的内建类型且不改变,可以不消&。
有了这个局限操纵,C++算是一猛进步呀。
原始字符串
传统C/C++应用包含字符串,用\来做逃脱而字符。如许,我们会在代码中看到一堆的\\\\\\
其实很影响浏览。如今很多说话都支撑正则表达式了,而正则中最多也恰是\\如许的符号,让C++来应用,my god!
。我感觉C++可能鉴戒了python的R字符串,和perl的定界符规矩,引出本身的原始字符串,在原始字符串中,不存在逃脱语义。写法如下:
R(string) 写法一
Rdelimiter(string)delimiter 写法二
更详尽的论说,筹算放在正则表达式时评论辩论。
新增类型申明符
ob0101:
默示二进制的5
F : 申明是一个浮点型常量 3F
L : 前缀应用申明字符串中字符是wchar_t, 后缀应用申明是一个 long
p :十六进制数(2^p), 即左移p。
增长对 Unicode 的支撑
字符串:
char utf_8[] = u8This is UTF-8
encoded.;
char16_t utf16[] = uThis is UTF-16 encoded.;
char32_t utf32[] = UThis is UTF-32
encoded.;
对unicode常量,应用\u逃脱,加上一个十六进制量
char utf_8[] = u8\u2018;
char16_t utf16[] = u\u2018;
char32_t
utf32[] = U\u2018;
同样,表达式可以应用原始字符串
感慨:C++错杂太多了,多了太多器材了,每个常识点都是一大章的器材,看来,路漫漫呀!
彼此相爱,却不要让爱成了束缚:不如让它成为涌动的大海,两岸乃是你们的灵魂。互斟满杯,却不要同饮一杯。相赠面包,却不要共食一个。一起歌舞欢喜,却依然各自独立,相互交心,却不是让对方收藏。因为唯有生命之手,方能收容你们的心。站在一起却不要过于靠近。—— 纪伯伦《先知》
More extensions to C , Some features of C++11
对于稍微有些C++的同窗,可能都知道C++和C的一些首要差别,大的差别就是一个是面向对象,一个是面向过程,这就涉及到对象; 同时,还有定名空间的引入,防止变量名冲突; 还有struct支撑成员函数等。 我就持续注释一些更须要重视的一些不合,一些是C++11中的器材。
引用
可以经由过程引用批改它引的对象,然则不克不及改变它本身。这么听来,就像是常量指针, 别的,引用也让代码加倍天然,不像c里边会呈现一堆的&来默示传址调用。
int a=1;
int &r=a;
int const rr = a; // intconst 和
int&是同一个器材,引用只是一个语法糖。
int &r=a;
int const rr = a; // intconst 和
int&是同一个器材,引用只是一个语法糖。
应用引用时,有几点须要记住:
引用定义时必须初始化! 其实看上方的法度例子就知道, const的器材都必须初始化
不要在函数中返回局部变量的引用
函数中是否应用引用的场合
引用,可以当做函数参数传入,如许就可能会批改所引用对象。指针也能达到如许的目标,如许多几许少会造成一些困惑,我们可以依从一些原则:
若形参是内建类型(int double char等),且我们不须要改变实参值,直接传值调用
若形参时内建类型,且我们须要批改它,那就经由过程指针调用
若形参类型是类,布局体等,我们不须要改变它的成员变量,采取 const &
调用
调用
若形参类型是类等,需要改变,采取引用&调用
应用引用调用,可以或许避免机关函数的调用,节俭开支。
别的,须要实现链式操纵的,返回值选择引用类型,也能避免机关函数的调用。经典例子就是 “cout”
右值引用 (对C++11不是很熟悉,会有一些懂得上的错误,请斧正)
C++11中多了个右值引用。 主如果因为姑且变量(右值)不克不及很好的同 const&
很好的区分隔来,是以C++11多了个右值引用&&。
很好的区分隔来,是以C++11多了个右值引用&&。
举例申明下:
int intVa()
{
return 5;
}
int& a = intVal(); // 错误!
引用姑且变量
int const& a = intVal(); //
正确,引用不变姑且变量
int a = &intVal(); // 错误!
intVal()不是左值
{
return 5;
}
int& a = intVal(); // 错误!
引用姑且变量
int const& a = intVal(); //
正确,引用不变姑且变量
int a = &intVal(); // 错误!
intVal()不是左值
我们持续看:
void receive(int& value){++value; cout <<“L-value parameter\n”;} // 左值引用版本
void receive(int&&
value){++value; cout << R-value
parameter\n;} // 右值引用版本
void
receive(int const& value)
{++value; cout << L-value const
parameter\n;} // ++value不克不及有,不然编译错误。这算是右值引用和const&的差别。
void receive(int&&
value){++value; cout << R-value
parameter\n;} // 右值引用版本
void
receive(int const& value)
{++value; cout << L-value const
parameter\n;} // ++value不克不及有,不然编译错误。这算是右值引用和const&的差别。
如此调用:
int main()
{
receive(18); //
R-value 19
int v = 5;
int const& cri =
v;
receive(cri); // L-value
const
receive(v); // L-value
6
receive(intVal()); // R-value
6
}
{
receive(18); //
R-value 19
int v = 5;
int const& cri =
v;
receive(cri); // L-value
const
receive(v); // L-value
6
receive(intVal()); // R-value
6
}
若我们把 void receive(int& value)删除,则receive(v) 返回 L-value
const parameter。 函数重载的右值引用版本,仅在匿名变量传入时激发。
const parameter。 函数重载的右值引用版本,仅在匿名变量传入时激发。
别的,右值引用版本函数中,可以对value进行操纵,可以看出,右值引用 用于获取 匿名姑且变量 的 把持权,而 int
const& 版本的却不可。
const& 版本的却不可。
重视下:
若引入别的个重载版本 void(int value), 那么将产生错误,因为该例中,匿名变量也可以解析成 int
型,导致重载冲突。
型,导致重载冲突。
别的,右值引用的进阶应用是 是 移动语义 move semantics 和 完美转发 perfect
forwarding 的根蒂根基。移动语义我临时还不懂啥,今后再讲述。
forwarding 的根蒂根基。移动语义我临时还不懂啥,今后再讲述。
强类型-列举类
C++中,列举类型其实就是int,不合列举类型可以经由过程static_cast<int>
来进行斗劲操纵;别的,不合列举类型的内部值不克不及雷同,因为C++中列举类型的感化局限不被列举名所限,而是受感化域限制。
来进行斗劲操纵;别的,不合列举类型的内部值不克不及雷同,因为C++中列举类型的感化局限不被列举名所限,而是受感化域限制。
C++11中,引入了 enum class ,来解决上述题目。
enum class CharEnum: unsigned char //
默认是int,可以经由过程这个“:”符号改变
{
NOT_OK, // 默认 0
OK //
自增1
};
默认是int,可以经由过程这个“:”符号改变
{
NOT_OK, // 默认 0
OK //
自增1
};
应用时,要参加列举类名与感化域符,即 CharEnum::OK.
前向声明如下
enum Enum1; // Illegal: no size
available
enum Enum2: unsigned int; // Legal in C++11:
explicitly declared type
enum class
Enum3; // Legal in C++11: default int type is
used
enum class Enum4: char; // Legal in C++11:
explicitly declared type
available
enum Enum2: unsigned int; // Legal in C++11:
explicitly declared type
enum class
Enum3; // Legal in C++11: default int type is
used
enum class Enum4: char; // Legal in C++11:
explicitly declared type
初始化列表
c说话中,可以用大括号包含一个初始化列表来初始化数组、布局体。C++11把这个概念持续扩大了,引入了
initializer_list<Type>
这个模本类,可以扩大初始化类,同时也能对初始化列表进行个性化操纵。 应用前,要包含头文件 <initializer_list>
。同时,可以将初始化列表当做函数形参传入。
void values(initializer_list<int> iniValues)
{
cout << Initializer list having
<< iniValues.size() << values\n;
for
(
initializer_list<int>::const_iterator begin =
iniValues.begin();
begin !=
iniValues.end();
++begin
)
cout << Value: << begin << \n;
}
{
cout << Initializer list having
<< iniValues.size() << values\n;
for
(
initializer_list<int>::const_iterator begin =
iniValues.begin();
begin !=
iniValues.end();
++begin
)
cout << Value: << begin << \n;
}
这个常识点Mark下,今后持续深切懂得,记得在 boost 中如同也有类似的器材。
auto 和 decltype 这个我感觉,好了
因为C++的声明可能会很是错杂难懂,C++11将曾经的auto关键字,使其可以或许主动解析类型,不错,基于boost的改进。
auto 和 decltype
功能异常强大,不过小我认为,还是要把模板常识搞透了再深切应用这个关键字斗劲好,根蒂根基神马的,最首要的了。
功能异常强大,不过小我认为,还是要把模板常识搞透了再深切应用这个关键字斗劲好,根蒂根基神马的,最首要的了。
int (fun())[10], 默示
fun是个函数,返回一个指向int数组[10]的指针。如许不好懂得,用上auto后,一切这么天然
fun是个函数,返回一个指向int数组[10]的指针。如许不好懂得,用上auto后,一切这么天然
auto func() -> int()[10];
别的,比如 vector<int>::const_iterator ci = v.begin();
可以改写成 auto ci = v.begin(); 例子很多,信赖auto的应用,会让C++加倍受迎接。
可以改写成 auto ci = v.begin(); 例子很多,信赖auto的应用,会让C++加倍受迎接。
类型定义和 ‘using’ 声明
比如 unsigned long int compute(double, double),
这个函数指针的声明,应用typedef可以变成如许:
这个函数指针的声明,应用typedef可以变成如许:
typedef unsigned long int(pfun)(double, double);
然则,我们声明时 pfun f;
时,袒护了Pfun实际上是一个指针的事实,必须看typedef定义才知道。关于这点,我很诟病,导致我函数指针一向没学好。C++11中将这点进行了升华,采取using
关键字:
时,袒护了Pfun实际上是一个指针的事实,必须看typedef定义才知道。关于这点,我很诟病,导致我函数指针一向没学好。C++11中将这点进行了升华,采取using
关键字:
using pfun =
unsigned long int(double, double);
或者和auto共同:
using
pfun = auto (double,double)
-> unsigned long
int;
unsigned long int(double, double);
或者和auto共同:
using
pfun = auto (double,double)
-> unsigned long
int;
for轮回的局限操纵
传统C/C++ 的for采取标准的
for(init;cong;next)语句,这对遍历的应用,不那么的便捷,很多说话都供给结局限操纵符,在STL的算法库也包含了for_each办法,然则还是不敷便捷。C++11中引入了for的局限操纵版本:
for(init;cong;next)语句,这对遍历的应用,不那么的便捷,很多说话都供给结局限操纵符,在STL的算法库也包含了for_each办法,然则还是不敷便捷。C++11中引入了for的局限操纵版本:
int array[100];
for (auto &element:array){...}
这里,推荐应用auto,避免思惟肩负在解析类型上。 同时,element是变量名,默示array中每次遍历的元素。
引用操纵符很是首要,若是要批改元素或array是类类型,则用引用; 若是类类型,但不改变,用const&;
通俗的内建类型且不改变,可以不消&。
引用操纵符很是首要,若是要批改元素或array是类类型,则用引用; 若是类类型,但不改变,用const&;
通俗的内建类型且不改变,可以不消&。
有了这个局限操纵,C++算是一猛进步呀。
原始字符串
传统C/C++应用包含字符串,用\来做逃脱而字符。如许,我们会在代码中看到一堆的\\\\\\
其实很影响浏览。如今很多说话都支撑正则表达式了,而正则中最多也恰是\\如许的符号,让C++来应用,my god!
。我感觉C++可能鉴戒了python的R字符串,和perl的定界符规矩,引出本身的原始字符串,在原始字符串中,不存在逃脱语义。写法如下:
其实很影响浏览。如今很多说话都支撑正则表达式了,而正则中最多也恰是\\如许的符号,让C++来应用,my god!
。我感觉C++可能鉴戒了python的R字符串,和perl的定界符规矩,引出本身的原始字符串,在原始字符串中,不存在逃脱语义。写法如下:
R(string) 写法一
Rdelimiter(string)delimiter 写法二
更详尽的论说,筹算放在正则表达式时评论辩论。
新增类型申明符
ob0101:
默示二进制的5
F : 申明是一个浮点型常量 3F
L : 前缀应用申明字符串中字符是wchar_t, 后缀应用申明是一个 long
p :十六进制数(2^p), 即左移p。
增长对 Unicode 的支撑
字符串:
char utf_8[] = u8This is UTF-8
encoded.;
char16_t utf16[] = uThis is UTF-16 encoded.;
char32_t utf32[] = UThis is UTF-32
encoded.;
char utf_8[] = u8This is UTF-8
encoded.;
char16_t utf16[] = uThis is UTF-16 encoded.;
char32_t utf32[] = UThis is UTF-32
encoded.;
对unicode常量,应用\u逃脱,加上一个十六进制量
char utf_8[] = u8\u2018;
char16_t utf16[] = u\u2018;
char32_t
utf32[] = U\u2018;
char utf_8[] = u8\u2018;
char16_t utf16[] = u\u2018;
char32_t
utf32[] = U\u2018;
同样,表达式可以应用原始字符串