敲了几天的基础知识demo,发现特别容易忘记,于是决定接下来的每一天都把敲过的基础代码贴到博客上,一来是自己把知识点重新梳理,加深理解;二来是把自己对一些问题的解决办法都记录下来,以便以后备忘。
今天的知识点比较零乱,我得好好整理。
1.引用包装器
#include
template<typename T>
void com(T arg)
{
std::cout << &arg << std::endl;
arg++;
}
void main()
{
int num = 20;
std::cout << &num << " " << num << std::endl;
com(std::ref(num));//std::ref//会把传入的值包装成可引用的值
com(num);
std::cout << &num << " " << num << std::endl;
std::cin.get();
}
2.C++智能指针
unique_ptr是一个独享所有权的智能指针,它提供了严格语义上的所有权,包括:
1,拥有它所指向的对象;
2,无法进行复制构造,也无法进行复制赋值操作。也就是说,我们无法得到指向同一个对象的两个unique_ptr。但是可以进行移动构造和移动赋值操作。
3,保存指向某个对象的指针,当它本身被删除释放的时候,会使用给定的删除器释放它所指向的对象。
c++11新出现的智能指针auto_ptr,存在于头文件memory中。
下面的代码是VS2013里面的源码:
template<class _Ty,
class _Dx> // = default_delete<_Ty>
class unique_ptr
: private _Unique_ptr_base<_Ty, _Dx,
is_empty<_Dx>::value
|| is_same, _Dx>::value>
{ // non-copyable pointer to an object
public:
typedef unique_ptr<_Ty, _Dx> _Myt;
typedef _Unique_ptr_base<_Ty, _Dx,
is_empty<_Dx>::value
|| is_same, _Dx>::value> _Mybase;
typedef typename _Mybase::pointer pointer;
typedef _Ty element_type;
typedef _Dx deleter_type;
using _Mybase::get_deleter;
unique_ptr() _NOEXCEPT
: _Mybase(pointer())
{ // default construct
static_assert(!is_pointer<_Dx>::value,
"unique_ptr constructed with null deleter pointer");
}
unique_ptr(nullptr_t) _NOEXCEPT
: _Mybase(pointer())
{ // null pointer construct
static_assert(!is_pointer<_Dx>::value,
"unique_ptr constructed with null deleter pointer");
}
_Myt& operator=(nullptr_t) _NOEXCEPT
{ // assign a null pointer
reset();
return (*this);
}
explicit unique_ptr(pointer _Ptr) _NOEXCEPT
: _Mybase(_Ptr)
{ // construct with pointer
static_assert(!is_pointer<_Dx>::value,
"unique_ptr constructed with null deleter pointer");
}
unique_ptr(pointer _Ptr,
typename _If::value, _Dx,
const typename remove_reference<_Dx>::type&>::type _Dt) _NOEXCEPT
: _Mybase(_Ptr, _Dt)
{ // construct with pointer and (maybe const) deleter&
}
unique_ptr(pointer _Ptr,
typename remove_reference<_Dx>::type&& _Dt) _NOEXCEPT
: _Mybase(_Ptr, _STD move(_Dt))
{ // construct by moving deleter
static_assert(!is_reference<_Dx>::value,
"unique_ptr constructed with reference to rvalue deleter");
}
unique_ptr(unique_ptr&& _Right) _NOEXCEPT
: _Mybase(_Right.release(),
_STD forward<_Dx>(_Right.get_deleter()))
{ // construct by moving _Right
}
template<class _Ty2,
class _Dx2,
class = typename enable_if::value
&& is_convertible<typename unique_ptr<_Ty2, _Dx2>::pointer,
pointer>::value
&& ((is_reference<_Dx>::value && is_same<_Dx, _Dx2>::value)
|| (!is_reference<_Dx>::value
&& is_convertible<_Dx2, _Dx>::value)),
void>::type>
unique_ptr(unique_ptr<_Ty2, _Dx2>&& _Right) _NOEXCEPT
: _Mybase(_Right.release(),
_STD forward<_Dx2>(_Right.get_deleter()))
{ // construct by moving _Right
}
template<class _Ty2,
class = typename enable_if::value
&& is_same<_Dx, default_delete<_Ty> >::value,
void>::type>
unique_ptr(auto_ptr<_Ty2>&& _Right) _NOEXCEPT
: _Mybase(_Right.release())
{ // construct by moving _Right
}
template<class _Ty2,
class _Dx2>
typename enable_if::value
&& is_convertible<typename unique_ptr<_Ty2, _Dx2>::pointer,
pointer>::value,
_Myt&>::type
operator=(unique_ptr<_Ty2, _Dx2>&& _Right) _NOEXCEPT
{ // assign by moving _Right
reset(_Right.release());
this->get_deleter() = _STD forward<_Dx2>(_Right.get_deleter());
return (*this);
}
_Myt& operator=(_Myt&& _Right) _NOEXCEPT
{ // assign by moving _Right
if (this != &_Right)
{ // different, do the move
reset(_Right.release());
this->get_deleter() = _STD forward<_Dx>(_Right.get_deleter());
}
return (*this);
}
void swap(_Myt& _Right) _NOEXCEPT
{ // swap elements
_Swap_adl(this->_Myptr, _Right._Myptr);
_Swap_adl(this->get_deleter(),
_Right.get_deleter());
}
~unique_ptr() _NOEXCEPT
{ // destroy the object
if (this->_Myptr != pointer())
this->get_deleter()(this->_Myptr);
}
typename add_reference<_Ty>::type operator*() const
{ // return reference to object
return (*this->_Myptr);
}
pointer operator->() const _NOEXCEPT
{ // return pointer to class object
return (_STD pointer_traits::pointer_to(**this));
}
pointer get() const _NOEXCEPT
{ // return pointer to object
return (this->_Myptr);
}
explicit operator bool() const _NOEXCEPT
{ // test for non-null pointer
return (this->_Myptr != pointer());
}
pointer release() _NOEXCEPT
{ // yield ownership of pointer
pointer _Ans = this->_Myptr;
this->_Myptr = pointer();
return (_Ans);
}
void reset(pointer _Ptr = pointer()) _NOEXCEPT
{ // establish new pointer
pointer _Old = this->_Myptr;
this->_Myptr = _Ptr;
if (_Old != pointer())
this->get_deleter()(_Old);
}
unique_ptr(const _Myt&) = delete;
_Myt& operator=(const _Myt&) = delete;
};
下面简陋对比一下auto_ptr和unique_ptr的区别:
double *p = new double;//为指针分配内存
std::auto_ptr<double> autop(p);
std::unique_ptr pdb(new double);
3.调试以及静态断言
在使用前需包含assert.h头文件
static_assert(sizeof(num) >= 4, "yincheng error");//静态断言
//各种宏可以更好地调试代码,迅速锁定代码错误在哪一行
cout << __FILE__ << endl;
cout << __LINE__ << endl;
cout << __DATE__ << endl;
cout << __TIME__ << endl;
cout << __FUNCTION__ << endl;
4.c++别名
typedef int(*ADD)(int a, int b);
using FUNC = int (*)(int a, int b);//别名
using co = std::ios_base::fmtflags;//using只可以用于简写数据类型
5.c++多线程
要使用C++多线程,需包含thread.h头文件,同时
using namespace std::this_thread;
// thread::hardware_concurrency线程
auto n = thread::hardware_concurrency();
std::cout << n << std::endl;
//获取当前线程编号
std::cout << "thread=" << get_id() << std::endl;
thread thread1(msg);//创建多线程
thread thread2(msg);
thread1.join();//开始执行
thread2.join();
这样即可实现并发执行。
6.模板元编程
/主要思想
//
//利用模板特化机制实现编译期条件选择结构,利用递归模板实现编译期循环结构,模板元程序则由编译器在编译期解释执行。
//
//优劣及适用情况
//
//通过将计算从运行期转移至编译期,在结果程序启动之前做尽可能多的工作,最终获得速度更快的程序。也就是说模板元编程的优势在于:
//
//1.以编译耗时为代价换来卓越的运行期性能(一般用于为性能要求严格的数值计算换取更高的性能)。通常来说,一个有意义的程序的运行次数(或服役时间)总是远远超过编译次数(或编译时间)。
//
//2.提供编译期类型计算,通常这才是模板元编程大放异彩的地方。
//
//模板元编程技术并非都是优点:
//
//1.代码可读性差,以类模板的方式描述算法也许有点抽象。
//
//2.调试困难,元程序执行于编译期,没有用于单步跟踪元程序执行的调试器(用于设置断点、察看数据等)。程序员可做的只能是等待编译过程失败,然后人工破译编译器倾泻到屏幕上的错误信息。
//
//3.编译时间长,通常带有模板元程序的程序生成的代码尺寸要比普通程序的大,
//
//4.可移植性较差,对于模板元编程使用的高级模板特性,不同的编译器的支持度不同。
//模板元吧运行时消耗的时间,在编译期间优化
//模板元编程递归实现斐波那契数列计算,大大提高运行速度
template<int N>
struct data
{
enum a{ res = data1>::a::res + data2>::a::res
};
};
template<>
struct data<1>
{
enum a{res =1};
};
template<>
struct data<2>
{
enum a{res= 1 };
};
//普通函数递归实现
int getdata(int n)
{
if (n==1 || n==2)
{
return 1;
}
else
{
return getdata(n - 1) + getdata(n - 2);
}
}
void main()
{
const int myint = 40;
int num = data::res;//<>内部不可以有变量
std::cout << num << std::endl;
std::cout << getdata(40) << std::endl;
std::cin.get();
}
7.内部函数绑定
#include
#include//处理函数
using namespace std;
using namespace std::placeholders;
//仿函数,创建一个函数指针,引用一个结构体内部或者一个类内部的公有函数
struct MyStruct
{
void add(int a)
{
cout << a << endl;
}
void add2(int a,int b)
{
cout << a +b<< endl;
}
void add3(int a, int b,int c)
{
cout << a + b +c<< endl;
}
};
void main()
{
MyStruct struct1;
//创建函数指针,类结构体,数据私有,代码共享
//函数通过调用,调用需要传递对象名进行区分
void(MyStruct::*p)(int a) = &MyStruct::add;
}
int main1()
{
MyStruct struct1;
//auto自动变量,地址,函数指针,bind绑定
//第一个参数引用内部函数,绑定一个实体对象,
auto func = bind(&MyStruct::add, &struct1, _1);
auto func2 = bind(&MyStruct::add2, &struct1,_1, _2);
auto func3 = bind(&MyStruct::add3, &struct1, _1, _2,_3);
func(100);
func2(10, 20);
func3(10, 20,30);
cin.get();
return 0;
}