C++相关闲碎记录(2)

1、误用shared_ptr

int* p = new int;
shared_ptr sp1(p);
shared_ptr sp2(p);  //error 
// 通过原始指针两次创建shared_ptr是错误的

shared_ptr sp1(new int);
shared_ptr sp2(sp1);  //ok

如果对C++相关闲碎记录(1)中记录的shared_ptr的使用例子修改为如下:父类添加孩子的shared_ptr时调用下面这个函数来实现,同样会出现问题:

class Person {
public:
    string name;
    shared_ptr mother;
    shared_ptr father;
    vector> kids;   //使用weak_ptr

    Person(const string& n, shared_ptr m = nullptr,
           shared_ptr f = nullptr) :name(n), mother(m), father(f) {}
        
    ~Person() {
        cout << "delete " << name << endl;
    }

    void setParentAndTheirKids(shared_ptr m = nullptr, shared_ptr f = nullptr) {
        mother = m;
        father = f;
        if (m != nullptr) {
            m->kids.push_back(shared_ptr(this));  //error
            // 为什么这里会报错,因为this所指的对象已经有一个shared_ptr了,再通过这种方式创建shared_ptr就会报错,因为会重新开启一个拥有者团队
        }
        if (f != nullptr){
            f->kids.push_back(shared_ptr(this)); //error
        }
    }
};

shared_ptr initFamily(const string& name) {
    shared_ptr mom(new Person(name + "'s mom"));
    shared_ptr dad(new Person(name + "'s dad"));
    shared_ptr kid(new Person(name));
    kid->setParentAndTheirKids(mom, dad);
    return kid;
}

使用enable_shared_from_this

#include 
#include 
#include 
#include 
using namespace std;

class Person : public enable_shared_from_this {
  public:
    string name;
    shared_ptr mother;
    shared_ptr father;
    vector> kids;  // weak pointer !!!

    Person (const string& n)
     : name(n) {
    }

    void setParentsAndTheirKids (shared_ptr m = nullptr,
                                 shared_ptr f = nullptr) {
        mother = m;
        father = f;
        if (m != nullptr) {
            m->kids.push_back(shared_from_this());
        }
        if (f != nullptr) {
            f->kids.push_back(shared_from_this());
        }
    }

    ~Person() {
      cout << "delete " << name << endl;
    }
};

shared_ptr initFamily (const string& name)
{
    shared_ptr mom(new Person(name+"'s mom")); 
    shared_ptr dad(new Person(name+"'s dad")); 
    shared_ptr kid(new Person(name)); 
    kid->setParentsAndTheirKids(mom,dad); 
    return kid;
}

int main()
{
    shared_ptr p = initFamily("nico");
    cout << "nico's family exists" << endl;
    cout << "- nico is shared " << p.use_count() << " times" << endl;
    cout << "- name of 1st kid of nico's mom: " 
         << p->mother->kids[0].lock()->name << endl;

    p = initFamily("jim");
    cout << "jim's family exists" << endl;
}

shared_ptr各种操作:

C++相关闲碎记录(2)_第1张图片

 C++相关闲碎记录(2)_第2张图片

shared_ptr sp(new int);
shared_ptr(static_cast(sp.get()))   //error
static_pointer_cast(sp)

std::unique_ptr up = new int;  //error
std::unique_ptr up(new int); // ok

unique_ptr不必一定拥有对象,也可以是empty。

std::unique_ptr up;
可以赋值为nullptr或者调用reset
up = nullptr;
up.reset();

unique_ptr可以调用release(),释放所拥有的对象,并将所有权交给调用者。

std::unique_ptr up(new std::string("nico"));
std::string* sp = up.release();

2、转移unique_ptr的拥有权

std::string* sp = new std::string("hello");
std::unique_ptr up1(sp);
std::unique_ptr up(new std::string[10]);  //ok
此偏特化不再提供操作符*和->,而提供[]操作符,访问array中的一个对象时,使用[]

std::cout << *up << std::endl; //error
std::cout << up[0] << std::endl;  //ok

指定自定义删除器:通过类的方式指定

class ClassADeleter {
public:
    void operator() (ClassA* p) {
        std::cout << "call delete for ClassA object" << std::endl;
        delete p;
    }
};

std::unique_ptr up(new ClassA());

如果是个函数或者lambda,必须声明deleter的类型为void(*)(T*)或者std::function,要不就使用decltype,例如要为array of int指定自己的deleter,并以lambda形式呈现:

std::unique_ptr up(new int[10], 
                                        [](int* p) {
                                            delete []p;});


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

或者
auto l = [](int*) {delete [] p;};
std::unique_ptr> up(new int[10], l);

 为了避免传递function pointer 或者lambda 时必须指明deleter的类型,你可以使用alias template

template
using uniquePtr = std::unique_ptr;

uniquePtr up(new int[10], [](int* p) {delete [] p;});

unique_ptr各种操作:

C++相关闲碎记录(2)_第3张图片

 3、numeric_limits<>

#include 
#include 
#include 
using namespace std;

int main()
{
   // use textual representation for bool
   cout << boolalpha;

   // print maximum of integral types
   cout << "max(short): " << numeric_limits::max() << endl;
   cout << "max(int):   " << numeric_limits::max() << endl;
   cout << "max(long):  " << numeric_limits::max() << endl;
   cout << endl;

   // print maximum of floating-point types
   cout << "max(float):       "
        << numeric_limits::max() << endl;
   cout << "max(double):      "
        << numeric_limits::max() << endl;
   cout << "max(long double): "
        << numeric_limits::max() << endl;
   cout << endl;

   // print whether char is signed
   cout << "is_signed(char): "
        << numeric_limits::is_signed << endl;
   cout << endl;

   // print whether numeric limits for type string exist
   cout << "is_specialized(string): "
        << numeric_limits::is_specialized << endl;
}

 4、type trait的使用

#include 
#include 
#include 
using namespace std;

// type trait
template 
void foo_impl(T val, true_type) {
    std::cout << "Integer" << std::endl;
}

template 
void foo_impl(T val, false_type) {
    std::cout << "not Integer" << std::endl;
}

template 
void foo(T val) {
    foo_impl(val, std::is_integral());
}

int main()
{
    double d_a = 1.2;
    long long int ll_b = 33333;
    foo(d_a);
    foo(ll_b);
}

输出:
not Integer
Integer
类型判断工具

C++相关闲碎记录(2)_第4张图片

 用以阐明class细节的traitC++相关闲碎记录(2)_第5张图片
#include 
#include 
#include 
using namespace std;


int main()
{
    std::cout << boolalpha << is_const::value << endl;                    //false
    std::cout << boolalpha << is_const::value << endl;     //true
    std::cout << boolalpha << is_const::value << endl;             //true
    std::cout << boolalpha << is_const::value << endl;             //false
    std::cout << boolalpha << is_const::value << endl;             //false
    std::cout << boolalpha << is_const::value << endl;                 //false
    std::cout << boolalpha << is_const::value << endl;           //true
    std::cout << boolalpha << is_const::value << endl;                  //false
    std::cout << boolalpha << is_const::value << endl;            //true

    return 0;
}

 指向const类型的非常量指针或者引用,并不是一个常量,尽管内含元素是常量,例如const int* 并不是常量,只是描述指针所指向的这个变量是常量类型,但是指针本身可以重新指向新的变量。

用以检测copy和move语义的那些个trait,只检测是否相应的表达式为可能,例如一个带有copy构造函数的(接受常量实参)但没有move构造函数的类型,仍然是move constructible.

用以检验类型关系的trait 

 C++相关闲碎记录(2)_第6张图片

int main()
{
    std::cout << boolalpha << is_assignable::value << endl;                               //false
    std::cout << boolalpha << is_assignable::value << endl;                              //true
    std::cout << boolalpha << is_assignable::value << endl;                             //false
    std::cout << boolalpha << is_assignable::value << endl;                             //true
    std::cout << boolalpha << is_assignable::value << endl;                            //false
    std::cout << boolalpha << is_assignable::value << endl;                             //false
    std::cout << boolalpha << is_assignable::value << endl;               //false
    std::cout << boolalpha << is_assignable::value << endl;               //true
    
    std::cout << boolalpha << is_constructible::value << endl;                                 //true
    std::cout << boolalpha << is_constructible::value << endl;                            //true
    std::cout << boolalpha << is_constructible::value << endl;                           //true
    std::cout << boolalpha << is_constructible::value << endl;                          //false
    std::cout << boolalpha << is_constructible::value << endl;                          //false
    std::cout << boolalpha << is_constructible::value << endl;            //false
    std::cout << boolalpha << is_constructible::value << endl;            //true
    std::cout << boolalpha << is_constructible::value << endl;  //true

    return 0;
}

5、类型修饰符

#include 
#include 
#include 
#include 
#include 
using namespace std;


int main()
{
    typedef int T;
    typedef add_const::type A;                //const int
    typedef add_lvalue_reference::type B;     //int&
    typedef add_rvalue_reference::type C;     //int&&
    typedef add_pointer::type D;              //int*
    typedef make_signed::type E;              //int
    typedef make_unsigned::type F;            //unsigned int
    typedef remove_const::type G;             //int
    typedef remove_reference::type H;         //int
    typedef remove_pointer::type I;           //int

    std::cout << boolalpha << is_const::value << std::endl;

    // 查看完整类型
    std::cout << abi::__cxa_demangle(typeid(A).name(),0,0,0 ) << std::endl;
    std::cout << typeid(B).name() << std::endl;

    std::cout << "A is same const int ?" << boolalpha << is_same::value << std::endl;
    std::cout << "B is same int& ?" << boolalpha << is_same::value << std::endl;

    typedef const int& T1;
    typedef add_const::type A1;                  // const int&
    typedef add_lvalue_reference::type B1;       //const int&
    typedef add_rvalue_reference::type C1;       //const int& (yes, lvalue remains lvalue)
    typedef add_pointer::type D1;                //const int*
    // typedef make_signed::type E1;             //undefined behavior
    // typedef make_unsigned::type F1;           //undefined bahavior
    typedef remove_const::type G1;               //const int&
    typedef remove_reference::type H1;           //const int
    typedef remove_pointer::type I1;             //cosnt int&

    std::cout << "A1 is same const int& ?" << boolalpha << is_same::value << std::endl;
    std::cout << is_const::value << std::endl;
    std::cout << "G1 is same const int& ?" << boolalpha << is_same::value << std::endl;

    return 0;
}

C++相关闲碎记录(2)_第7张图片

 指向某常量类型的reference本身并不是常量,所以不可以移除const,add_pointer<>必然包含使用remove_reference<>,然而make_signed<>和make_unsigned<>必须是整型,枚举型,bool除外,所以传入引用会导致不明确的行为。add_lvalue_reference<>把一个rvalue reference转换为一个lvalue reference,然而add_rvalue_reference<>并不会把一个lvalue reference转换为一个rvalue reference.

6、其他type trait 

#include 
#include 
#include 
#include 
#include 
using namespace std;


int main()
{
    std::cout << rank::value << std::endl;                   //0
    std::cout << rank::value << std::endl;                 //1
    std::cout << rank::value << std::endl;                //1
    std::cout << rank::value << std::endl;              //2
    std::cout << rank::value << std::endl;             //2

    std::cout << extent::value << std::endl;                 //0
    std::cout << extent::value << std::endl;               //0
    std::cout << extent::value << std::endl;              //3
    std::cout << extent::value << std::endl;            //0
    std::cout << extent::value << std::endl;           //3
    std::cout << extent::value << std::endl;         //3
    std::cout << extent::value << std::endl;        //6
    std::cout << extent::value << std::endl;        //0
   
    typedef remove_extent::type A;                           //int
    typedef remove_extent::type B;                         //int
    typedef remove_extent::type C;                        //int
    typedef remove_extent::type D;                      //int[8]
    typedef remove_extent::type E;                     //int[7]
    typedef remove_all_extents::type F;                      //int
    typedef remove_all_extents::type G;                      //int
    typedef remove_all_extents::type H;                    //int
    typedef remove_all_extents::type I;                   //int
    typedef remove_all_extents::type J;                 //int
    typedef remove_all_extents::type K;                //int
    return 0;
}

你可能感兴趣的:(c++)