学习《深入应用c++11》2

&&

  universal references(未定的引用类型),它必须被初始化,它是左值还是右值取决于它的初始化,如果&&被一个左值初始化,它就是一个左值;如果它被一个右值初始化,它就是一个右值;只有当发生自动类型推断时(如函数模板的类型自动推到,或auto关键字),&&才是一个universal references.

template<typename T>
void f(T&& param);                  //这里T的类型需要推导,所以&&是一个universal references

f(10);          //10是右值
int x = 10;     
f(x);           //x是左值


template<typename T>
class Test{
    Test(Test&& rhs);               //已定义特定的类型,&&是一个右值引用
};

template<typename T>
void f(std::vector<T>&& param);    //&&右值引用类型,因为在调用这个函数之前,vector<T>中的推断类型已经确定了,到调用f的时候没有类型推断

template<typename T>
void f(const T&& param);           //右值引用类型,universal references仅仅在T&&下发生,任何附加条件都会使之失效

  引用折叠:由于存在T&&这种类型,当它作为参数的时候,可能被一个左值引用或右值引用的参数初始化,这时经过类型推导的T&&类型,相比右值引用会发生类型的变化
折叠规则:

  1. 所有的右值引用叠加到右值引用上仍然还是一个右值引用(A&& && 变成 A&&)
  2. 所有的其他引用类型之间的叠加都将变成左值引用(A& & 变成 A&; A& && 变成 A&; A&& & 变成 A&)

  通过typeid(t).name()可以获取到数据类型,但在不同的编译器下,可能不完整;

//msvc
std::cout << typeid(T).name() << std::endl;

//gunc 通过__cxa_demangle将低级符号名解码(demangle)成用户级名字 头文件 #include <cxxabi.h>
char *real_name = abi::__cxa_demangle(typeid(T).name(), nullptr, nullptr, nullptr);
std::cout << real_name;
free(real_name);

std::move

  move实际上并不能移动任何东西,它唯一的功能是将一个左值强制转换为一个右值引用,方便实现移动构造。

std::forward 和 完美转发

  完美转发是指在函数模板中,完全依照模板的参数的类型,将参数传递给函数模板中调用的另外一个函数。

template<class T>
void Print(T & t)
{
    std::cout << "lvalue : " << t << std::endl;
}

template<class T>
void Print(T &&t)
{
    std::cout << "rvalue : " << t << std::endl;
}

template<class T>
void TestForward(T&& t)
{
    Print(t);
    Print(std::forward<T>(t));
    Print(std::move(t));
}

void test()
{
    TestForward(1);
    int x = 1;
    TestForward(x);
    TestForward(std::forward<int>(x));
}

万能函数包装器

template <class Function, class... Args>
inline auto FuncWrapper(Function &&f, Args &&... args) -> decltype(f(std::forward<Args>(args)...))
{
    return f(std::forward<Args>(args)...);
}

emplace_back 减少内存拷贝和移动

  emplace_back能就地通过参数构造对象,不需要拷贝或移动内存。

unordered container 无序容器

  C++11增加了无需容器unordered_map/unordered_multimap 和 unordered_set/unordered_multiset;由于这些容器中元素不是有序的,比map/multimap和set/multiset效率更高。map和set内部是红黑树,在插入元素时会自动排序,而无序容器内部是散列表(Hash Table),通过哈系,而不是排序来快速操作元素,使得效率更高

struct Key
{
    std::string first;
    std::string second;
};

struct KeyHash
{
    std::size_t operator()(const Key& key)const
    {
        return std::hash<std::string>()(key.first) ^ (std::hash<std::string>()(key.second) << 1);
    }
};

struct KeyEqual
{
    bool operator()(const Key &lhs, const Key &rhs) const
    {
        return lhs.first == rhs.first && lhs.second == rhs.second;
    }
};


std::unordered_map<Key,std::string,KeyHash,KeyEqual> munordermap = {
    {{"first","first"},"1"},
    {{"second","second"},"2"}
};

猜你喜欢

转载自www.cnblogs.com/s3320/p/12133789.html