1. 程式人生 > >lambda、pair、智能指針及時間函數

lambda、pair、智能指針及時間函數

-- nose lam iostream 標準庫 sink 單位 pty share

Lambda 表達式

auto f1 = [](int x, int y) { return x + y; };
cout << f1(2, 3) << endl;

int n = [] (int x, int y) { return x + y; }(5, 4);

int var;
decltype(var) var1; int

const int&& fx();
decltype(fx()); const int&&


templeate<typename T1, typename T2>
decltype(x+y) add(T1 x, T2 y); //錯誤x,y未在作用域

templeate<typename T1, typename T2>
auto add(T1 x, T2 y) -> decltype(x+y); //OK

通用工具
Pair <utility>

pair<T1,T2> p;
pair<T1,T2> p(val1,val2);
p.first;
p.second;
get<0>(p); //p.first
get<1>(p); //p.second
p1.swap(p2);
swap(p1,p2);
make_pair(val1,val2);


Touple 擴展pair,建議至少10個 <tuple>

tuple<int,float,string> t1(41,6.3,"nico");
get<0>(t1);

make_tuple(41,6.3,"nico");


元素可以是reference
string s;
tuple<string&> t(s);
get<0>(t) = "hello";

ref()、cref() <functional>

string s;
make_tuple(ref(s));


tuple<int,float,string> t(77,1.1,"s");
int i;
float f;
string s;
tie(i,f,s) = t; //建立一個內含reference的tuple


智能指針 <memory>

unique_ptr 獨占式擁有
unique_ptr<int> up(new string("nico"));
(*up)[0] = ‘N‘;
up->...


不允許賦值
unique_ptr<int> up = new int; //ERROR
必須直接初始化
unique_ptr<int> up(new int); //OK

unique_ptr<string> up;
up = nullptr;或up.reset(); //其內delete且賦值為nullptr


unique_ptr<string> up(new string("nico"));
string *sp = up.release();

if (up != nullptr)

if (up.get() != nullptr)

轉移擁有權
string *sp = new string("hello");
unique_ptr<string> up1(sp);
unique_ptr<string> up2(sp);//ERROR
unique_ptr<string> up3(std::move(up1));

函數參數是unique_ptr,則參數需要move

void sink(unique_ptr<ClassA> up)
{}

unique_ptr<ClassA> up(new ClassA);
sink(std::move(up));//調用之後up為空
//若想調用之後up也有效,則參數設為引用unique_ptr<ClassA> &up

函數返回unique_ptr,其擁有權移至調用端場景
unique_ptr<ClassA> source()
{
unique_ptr<ClassA> ptr(new ClassA);
...
return ptr;
}


針對Array

unique_ptr<string> up(new string[10]);//ERROR,能編譯

偏特化版本 自行調用delete[]
unique_ptr<string[]> up(new string[10]);
此版本不提供* 和 ->操作符,該而提供[]
*up; //ERROR
up[0];


當所指對象要求的不只是調用delete或delete[],就必須具體制定自己的deleter
class ClassADeleter
{
public:
void operator () (ClassA* p){
cout << "call delete for ClassA object" << endl;
delete p;
}
};

unique_ptr<ClassA,ClassADeleter> up(new ClassA());

如果你給的是個函數或lambda,就必須聲明deleter的類型為void(*)(T*)或std::function<void(T*)>, (頭文件<functional>)
要不就使用decltype

unique_ptr<int, void(*)(int*)> up(new int[10],
[](int* p){
...
delete[] p;
});

unique_ptr<int, std::function<void(int*)>> up(new int[10],
[](int* p){
...
delete[] p;
});

auto l = [](int* p){
...
delete[] p;
};
unique_ptr<int,decltype(l)>> up(new int[10], l);

shared_ptr 可以賦值、拷貝、比較

shared_ptr<string> pNico(new string("nico"));
shared_ptr<string> pNico{new string("nico")};

shared_ptr<string> pNico = new string("nico");//ERROR

shared_ptr<string> pNico = make_shared<string>("nico");

shared_ptr<string> pNico;
pNico = new string("nico");//ERROR
pNico.reset(new string("nico"));

pNico.use_count();//某個對象的當前擁有者數量


定義自己的Deleter
shared_ptr<string> pNico(new string("nico"),
[](string* p){
cout << "delete " << *p << endl;
delete p;
});

針對Array
shared_ptr<int> p(new int[10]);//ERROR,能編譯

shared_ptr<int> p(new int[10],
[](int* p){
delete[] p;
});

shared_ptr<int> p(new int[10],
std::default_delete<int[]>());

此與unique_ptr不同
unique_ptr<int> p(new int[10]);//能編譯
shared_ptr<int> p(new int[10]);//ERROR,不能編譯

shared_ptr不提供operator []

p.get()[2] = 2;
等同於
(&*p)[2] = 2;


誤用
int* p = new int;
shared_ptr<int> sp1(p);
shared_ptr<int> sp2(p);
ERROR,sp1、sp2都會在丟失p的擁有權時釋放相應資源即delete


shared_ptr<int> sp1(new int);
shared_ptr<int> sp2(sp1);


sp.reset();//放棄擁有權並重新初始化,使它像是empty
sp.reset(ptr);//放棄擁有權並重新初始化(擁有*ptr),使用默認delete
sp.reset(ptr,del);

make_shared(...);//
auto sp3 = make_shared<int>(1);


sp.get();//返回存儲的pointer
*sp
sp->
sp.use_count()
if (sp) //判斷sp是否為empty


挑選最大最小值 <algorithm>
min(a,b);
min(a,b,cmp);
min(initlist)
min(initlist,cmp)
max...
minmax(a,b) //返回pair<>,其first是最小值,second是最大值
minmax(a,b,cmp)
minmax(initlist)
minmax(initlist,cmp)


swap() <utility>

namespace std{
template<typename T>
inline void swap(T& a, T& b)...{
T tmp(std::move(a));
a = std::move(b);
b = std::move(tmp);
}
}

Class ratio<>的編譯期分數運算 <ratio>


ratio<5,3>; 3分之5
ratio<5,3>::num 5
ratio<5,3>::den 3

ratio<0>; //0, den默認為1

Clock和Timer <chrono>


duration 時間段 = tick(片刻數)*時間單位(分數) 1.5個1/3秒

timepoint 時間點 = 一個duration和一個opoch(起始點)


std::chrono::duration<int> twentySeconds(20);
std::chrono::duration<double, std::ratio<60>> halfAMinute(0.5);
std::chrono::duration<long, std::ratio<1,1000>> oneMillisecond(1);

std::chrono::huors
std::chrono::minutes
std::chrono::seconds twentySeconds(20);
std::chrono::milliseconds
std::chrono::microseconds
std::chrono::nanoseconds

隱式轉換可以轉換至較精準的單位類型
可以將小時轉換為秒,反之則不行


duration d
d.count() //返回d的tick數量
duration_cast<D>(d) //顯示轉換
duration::zero() //獲得長度為0的duration
duration::max() //
duration::min()
duration::rep() //獲得tick的類型
duration::period() //獲得單位類型的類型


Clock 和 Timepoint

Clock 定義一個epoch 和一個tick周期
clock::duration 獲得clock的duration類型
clock::rep 獲得tick類型 <=> clock::duration::rep
clock::period 獲得單位類型的類型 <=> clock::duration::period
clock::time_point 獲得clock的timepoint類型
clock::is_steady 如果clock是steady則為TRUE
clock::now() 獲得一個表示目前時間的time_point


C++標準庫提供了三個clock

1.system_clock 系統的即時時鐘 tick: 0.000100 milliseconds
is_steady:false
to_time_t()
form_time_t()


2.steady_clock tick: 1.000000 milliseconds


3.high_resolution_clock 當前系統中帶有最短tick周期的clock tick: 0.000100 milliseconds
is_steady:true


#include <chrono>
#include <ctime>
#include <string>
#include <iostream>

using namespace std;
using namespace std::chrono;

string asString(const system_clock::time_point& tp)
{
time_t t = system_clock::to_time_t(tp);
string ts;// = ctime(&t); //轉換為日歷時間
char arr[100];
memset(arr, 0, 100);
ctime_s(arr, 100, &t);
ts = arr;
if (ts.size() > 0)
ts.resize(ts.size() - 1); //移除末端的newline字符
return ts;
}

int main(int argc, _TCHAR* argv[])
{
//epoch:由clock的time_point的默認構造函數產出
system_clock::time_point tp;
//等價於
time_point<system_clock> tp1;
cout << "epoch: " << asString(tp) << endl;

tp = system_clock::now();
cout << "now: " << asString(tp) << endl;

tp = system_clock::time_point::min(); //出錯??
cout << "min: " << asString(tp) << endl;

tp = system_clock::time_point::max(); //出錯??
cout << "max: " << asString(tp) << endl;


return 0;
}


C 提供的 Date/Time函數

<time.h> --> <ctime>

clock_t 數值類型 long ,表示elapsed CPU time,由clock()返回
time_t 數值類型,表現timepoint
struct tm 被解開之日歷時間的類型


clock() 獲得elapsed CPU time,該程序從啟動到函數調用占用CPU的時間,
單位是1/CLOCKS_PER_SEC秒 1/1000 即 毫秒
time() 獲得當前時間,是個數值time_t t; time(&t);//same as:t = time(NULL);
difftime() 獲得2個time_t之間的差值,double,單位秒


localtime() 轉換time_t成為一個struct tm,考慮時區
gmtime() 轉換time_t成為一個struct tm,不考慮時區
asctime() 轉換struct tm成為一個標準日歷時間字符串
strftime() 轉換struct tm成為一個用戶自定義的日歷時間字符串
ctime() 轉換time_t成為一個標準日歷時間字符串,考慮時區
相當於asctime(localtime(t))
mktime() 轉換struct tm成為一個time_t並查詢其為星期中的哪一天,和一年中的第幾天

struct tm
{
int tm_sec; // seconds after the minute - [0, 60] including leap second
int tm_min; // minutes after the hour - [0, 59]
int tm_hour; // hours since midnight - [0, 23]
int tm_mday; // day of the month - [1, 31]
int tm_mon; // months since January - [0, 11]
int tm_year; // years since 1900
int tm_wday; // days since Sunday - [0, 6]
int tm_yday; // days since January 1 - [0, 365]
int tm_isdst; // daylight savings time flag
};


_time64和time_t默認情況下,等效於 __time64_t
如果需要強制編譯器將解釋time_t為舊的 32 位time_t,你可以定義 _USE_32BIT_TIME_T。
不建議這樣做,因為應用程序可能會在 2038 年 1 月 18 日後失效;64 位平臺上不允許使用此宏。

clock_t為long,一個帶符號的 32 位整數,和CLOCKS_PER_SEC宏定義為 1000
這樣,最多時鐘函數返回值為 2147483.647 秒,或大約 24.8 天
所以一般不使用此函數

lambda、pair、智能指針及時間函數