Input/output library
参考:https://en.cppreference.com/w/cpp/io
cerr
参考:https://zh.cppreference.com/w/cpp/io/cerr
cerr代表标准错误设备(standard error)。和cout一样,cerr将其输出结果定向到用户的终端。两者的唯一差别是,cerr的输出结果并无缓冲(bufferred)情形——它会立即显示于用户终端中。
操纵符
p31 endl 是事先定义好的操纵符(manipulator),由 iostream library 提供。所有的参见: https://en.cppreference.com/w/cpp/io/manip
cout 会事先输出到缓冲区,貌似是遇到一个回车刷新一次,所以 endl 会刷新,还可以用 std::flush 刷新。
open mode
参考:https://en.cppreference.com/w/cpp/io/ios_base/openmode
如果想要同时读写同一个文件,得定义一个 fstream 对象,为了以追加模式(append mode)打开,我们这样写:
std::fstream iofile("xxx.txt", std::ios_base::in || std::ios_base::app);
iostream iterator
示例代码:
#include <iostream>
#include <fstream>
#include <iterator>
#include <algorithm>
#include <vector>
#include <string>
int main()
{
std::ifstream in_file("input_file.txt");
std::ofstream out_file("output_file.txt");
if (!in_file || !out_file)
{
std::cerr << "!! unable to open the necessary files.\n";
return -1;
}
std::istream_iterator<std::string> is(in_file);
std::istream_iterator<std::string> eof;
std::vector<std::string> text;
std::copy(is, eof, std::back_inserter(text));
std::sort(text.begin(), text.end());
std::ostream_iterator<std::string> os(out_file, " ");
std::copy(text.begin(), text.end(), os);
}
注1:对标准输入设备而言,end-of-file 即代表last。只要在定义 istream_iterator 时不为它指定 istream 对象,它便代表了 end-of-file
注2:std::ostream_iterator<std::string> os(out_file, " "); 的第二个参数可以是 C-style 字符串,也可以是字符串常量。用来表示各个元素被输出时的分隔符。默认情形下,输出的各个元素之间并无分隔符。
标准库定义的 function object
六个算数运算、六个关系运算、三个逻辑运算。要想使用必须先包含:#include <functional>
adapter
binder adapter
https://en.cppreference.com/w/cpp/utility/functional/bind
insertion adapter
https://en.cppreference.com/w/cpp/iterator
从上面网站可以看到: 有这么多的 iterator adaptor,使用必须包含头文件:#include <iterator>
示例:
#include <iostream>
#include <vector>
#include <iterator>
int main()
{
std::vector<int> move_vec(5, 0);
std::vector<int> final_vec = { 1, 2, 3, 4 };
std::copy(move_vec.begin(), move_vec.end(), std::inserter(final_vec, std::next(final_vec.begin())));
for (auto mem : final_vec)
{
std::cout << mem << " ";
}
std::cout << std::flush;
}
operator .* 与operator ->*
在P120引出了运算符重载的规则,出现了这样的运算符,这里记录一下,见: https://stackoverflow.com/questions/6586205/what-are-the-pointer-to-member-and-operators-in-c#
struct X
{
void f() {}
void g() {}
};
typedef void (X::*pointer)();
pointer somePointer = &X::f;
X x;
(x.*somePointer)();
X* px = new X;
(px ->* somePointer)();
疑问:为啥类内的函数指针定义的时候必须要用取址符 & 呢?
我的观点:因为 member function 实际上转化的时候是变成一个 non-member function 外加一个 this 指针,因此需要一个实例才能正确调用,所以加一个取址符来说明。
好吧就是我想的这样,比如我的测试程序:
#include <iostream>
class Test
{
public:
void foo()
{
std::cout << " f " << std::endl;
}
};
int main()
{
void (Test::*fun_ptr)() = &Test::foo;
Test t;
(t.*fun_ptr)();
}
如果去掉 & 编译时会报错: error : call to non-static member function without an object argument
而如果是static的,则不需要this指针,所以可以直接调用:
#include <iostream>
class Test
{
public:
static void foo()
{
std::cout << " f " << std::endl;
}
};
int main()
{
void (*fun_ptr)() = Test::foo;
fun_ptr();
}
补充
P185:全局作用域(global scope)内的函数及对象,其地址也是一种常量表达式。
初识 sstream
#include <iostream>
#include <sstream>
int main()
{
std::ostringstream sstr;
std::string str;
sstr << 5 << "+" << 2 << "=" << 7 << std::endl;
str = sstr.str();
std::cout << str << std::endl;
}
好处是能自动将这类数值类型转换为相应的字符串,不需要我们再去处理。
异常
new可能会抛异常 bad_alloc ,标准库有:auto test = new (std::nothrow) std::vector<int>; ,这样如果 new 失败会返回0(nullptr),每次使用的时候都需要检验。
参考:https://en.cppreference.com/w/cpp/memory/new/nothrow
https://zh.cppreference.com/w/cpp/language/noexcept_spec
https://en.cppreference.com/w/cpp/language/exceptions
|