C++ Primer学习过程中疑惑点记录笔记
导引
【c++】一、size_t 和 size_type的区别
为了使自己的程序有很好的移植性,c++程序员应该尽量使用size_t和size_type而不是int, unsigned
size_t是全局定义的类型;size_type是STL类中定义的类型属性,用以保存任意string和vector类对象的长度
string::size_type 制类型一般就是unsigned int, 但是不同机器环境长度可能不同 win32 和win64上长度差别;size_type一般也是unsigned int
使用的时候可以参考: string::size_type a =123; vector
<int>
::size_type b=234; size_t b=456;size_t 使用的时候头文件需要
<cstddef>
;size_type 使用的时候需要<string>
或者<vector>
sizeof(string::size_type)
sizeof(vector<bool>
::size_type)
sizeof(vector<char>
::size_type)
sizeof(size_t)
上述长度均相等,长度为win32:4 win64:8二者联系:在用下标访问元素时,vector使用vector::size_type作为下标类型,而数组下标的正确类型则是size_t
【c++】二、const 和 constexpr的区别
链接:浅谈 C++ 中的 const 和 constexpr
const和constexpr都可以来修饰对象和函数。
修饰对象的时候两者之间最基本的区别是:
1、const
修饰一个对象表示它是常量。这暗示对象一经初始化就不会再变动了,并且允许编译器使用这个特点优化程序。这也防止程序员修改了本不应该修改的对象。
2、constexpr
是修饰一个常量表达式。但请注意constexpr
不是修饰常量表达式的唯一途径。
修饰函数的时候两者之间最基本的区别是:
1、const
只能用于非静态成员的函数而不是所有函数。它保证成员函数不修改任何非静态数据。
2、constexpr
可以用于含参和无参函数。constexpr
函数适用于常量表达式,只有在下面的情况下编译器才会接受constexpr
函数: (1)函数体必须足够简单,除了typedef
和静态元素,只允许有return语句。如构造函数只能有初始化列表,typedef
和静态元素 (实际上在C++14标准中已经允许定义语句存在于constexpr
函数体内了) (2)参数和返回值必须是字面值类型
常量表达式的概念如下
必须是可以在编译阶段被识别的。比如模版的参数/数组的大小。
template <int N>
class fixed_size_list
{ /*...*/ };
fixed_size_list<X> mylist; <-- X必须是字面值类型
int numbers[X]; <-- X必须是字面值类型
但是注意下面两点
用
constexpr
修饰某物并不保证它一定在编译时被计算,也可以在运行时被计算。 不用constexpr
也可能是一个常量表达式,如
int main()
{
const int N = 3;
int num[N] = {1,2,3,}; N是一个常量表达式
}
N在声明时初始化,满足常量表达式的标准,虽然没用constexpr
所以到底什么时候用
constexpr
? 像上面的N,虽然没有用constexpr
仍然是一个常量表达式。事实上,const本身和它的枚举类型若在声明时初始化那么就是一个常量表达式。
在函数中若有常量表达式那么必须用constexpr
,仅仅满足常量表达式的条件是不够的,如
template <int N>
class list
{ };
constexpr int sqr1(int arg)
{ return arg*arg; }
int sqr2(int arg)
{ return arg*arg; }
int main()
{
const int X = 2;
list<sqr1(X)> mylist1; 可以,因为sqr1时constexpr函数
list<sqr2(X)> mylist2; 不可以,因为sqr2不是constexpr函数
return 0;}
什么时候该同时使用两者?
在修饰变量的时候 修饰变量时没有必要同时使用const
和constexpr
因为constexpr
包含了const
的含义
constexpr const int N = 5;
constexpr int N = 5;
两行的意思完全相同
然而注意有一些情况
const
和constexpr
在修饰不同的东西,比如
static constexpr int N = 3;
int main()
{
constexpr const int *NP = &N;
return 0;
}
在这里
constexpr
和const
都必须要有。constexpr
表示NP指针本身是常量表达式,而const
表示指向的值是一个常量。去掉const
之后无法编译,因为不能用正常指针指向常量。
在修饰成员函数的时候 在C++11中,对成员函数而言
constexpr
同样包含const
的含义。
然而在C++14中可能已经改变了。如
constexpr void f();
以后可能必须写成
constexpr void f() const;
虽然目前写成const仍然有效,但最好使用constexpr来防止以后修改大量代码的可能性。
【c++】三、标准错误流Cerr
大家平时用到的输出有三个:cout、cerr、clog。
cout
:写到标准输出的ostream
对象;
cerr
:输出到标准错误的ostream
对象,通常用来输出警告和错误信息给程序的使用者;
clog
:也是输出标准错误流(和cerr
是一样的),用于产生程序执行的一般信息,很少用到。 区别
cout
经过缓冲后输出,默认情况下是显示器。这是一个被缓冲的输出,是标准输出;它在内存中对应开辟了一个缓冲区,用来存放流中的数据,当向cout
流插入一个endl
,不论缓冲区是否漫了,都立即输出流中所有数据,然后插入一个换行符. 可以被输出到文件,即可以重定向输出。
cerr
不经过缓冲而直接输出,一般用于迅速输出出错信息,是标准错误,默认情况下被关联到标准输出流,但它不被缓冲,也就说错误消息可以直接发送到显示器,而无需等到缓冲区或者新的换行符时,才被显示。
clog
流也是标准错误流,作用和cerr一样,区别在于cerr
不经过缓冲区,直接向显示器输出信息,而clog
中的信息存放在缓冲区,缓冲区满或者遇到endl
时才输出.
缓冲区的目的,就是减少刷屏的次数——比如,你的程序输出圣经中的一篇文章。不带缓冲的话,就会每写一个字母,就输出一个字母,然后刷屏。有了缓冲,你将看到若干句子“同时”就出现在了屏幕上(由内存翻新到显存,然后刷新屏幕)。
【c++】四、ifstream open 读取txt文件出现中文乱码的解决方法
链接:C++ ifstream open 读取txt文件出现中文乱码的解决方法
由于编解码的问题,txt读写会出现中文乱码,打开txt文件,点另存为,可看到编码方式有:
编码方式为UTF-8时,会出现中文乱码。
将编码方式换为ANSI时,问题解决。
【c++】五、main : 处理命令行选项
命令行给main函数提供实参,执行程序的过程:
#include <iostream>
using namespace std;
int main(int argc, char **argv)
{
cout << "argc= " << argc << endl;
for (int i = 0; i < argc; i++)
{
cout << "argv[" << i << "]=" << argv[i] << endl;
}
string str;
for (int i = 1; i < argc; i++) //注意 i 要从 1 开始
str += argv[i];
cout << "str = " << str << endl;
system("pause");
return 0;
}
1.在vs中 打开 “调试- 命令行选项 调试属性”
2.在 “调试 - 命令参数 ” 一项中输入argv 数组的其他元素
3.运行程序
注 : 当使用 argv 中的实参时, 一定要记得可选的实参从 argv[1] 开始; argv[0] 保存程序的名字, 而非用户输入