一、代理类
所谓的代理类就是以模仿和增强一些类型的行为为目的存在的类
class MyArray
{
public:
class MyArraySize
{
public:
MyArraySize(int size) : theSize(size) {}
int size() const { return theSize; }
operator int() const { return theSize; }
private:
int theSize;
};
MyArray(MyArraySize size) : size_(size), data_(new int[size.size()]) {}
int operator[](int index)
{
return data_[index];
}
bool operator==(const MyArray &temp)
{
return data_ == temp.data_;
}
MyArraySize size() { return size_; }
private:
int *data_;
MyArraySize size_;
};
class MyArray_
{
public:
// C++ 11之前没有explicit
MyArray_(int size) : size_(size), data_(new int[size]) {}
private:
int *data_;
int size_;
};
void func1(MyArray arr)
{
}
void func2(MyArray_ arr)
{
}
int main()
{
func2(10);
func1(10); // 错误,不能进行两次类型转换
func1(MyArray(10)); // 通过代理类,可以避免上面隐式转换的情况
return 0;
myArray arr(10);
auto size = arr.size(); // auto 推导为MyArray::MyArraySize
int size_ = arr.size(); // 因为存在operator int()隐式类型转换
}
二、临时变量的引用不要用引用来接
#include <vector>
#include <iostream>
class A
{
public:
A() { std::cout << "A::A()" << std::endl; }
A(int data) : _data(data) { std::cout << "A::A(int data)" << std::endl; }
A(const A &a) : _data(a._data)
{
std::cout << "A::A(const A &a)" << std::endl;
}
A(A &&a) : _data(a._data)
{
std::cout << "A::A(A &&a)" << std::endl;
}
~A() { std::cout << "A::~A()" << std::endl; }
int _data{100};
};
std::vector<A> func()
{
return {A(1), A(2), A(3), A(4), A(5)};
}
int main()
{
A aaa = func()[2]; // 发生拷贝
A &bbb = func()[3]; // 错误,引用了一个临时变量
return 0;
}
#include <vector>
#include <iostream>
std::vector<bool> features()
{
return {true, true, true, false, false};
}
int main()
{
bool highPriority = features()[4];
auto highPriority = features()[4]; // 错误写法,推导为引用类型的代理类
// auto推到为std::vector<bool>::reference
// reference在vector中其实是一个代理类
auto highPriority_ = static_cast<bool>(features()[4]);
return 0;
}
三、expressin template
#include <cassert>
#include <iostream>
#include <vector>
template <typename Derived>
void func(Base<Derived> derived)
{
derived.name();
}
// https://blog.csdn.net/HaoBBNuanMM/article/details/109740504
// CRTP中的基类模板
template <typename E>
class VecExpression
{
public:
// 通过将自己static_cast成为子类,调用子类的对应函数实现实现静态多态
double operator[](size_t i) const { return static_cast<E const &>(*this)[i]; }
size_t size() const { return static_cast<E const &>(*this).size(); }
};
// 将自己作为基类模板参数的子类 - 对应表达式编译树中的叶节点
class Vec : public VecExpression<Vec>
{
std::vector<double> elems;
public:
double operator[](size_t i) const { return elems[i]; }
double &operator[](size_t i) { return elems[i]; }
size_t size() const { return elems.size(); }
Vec(size_t n) : elems(n) {}
Vec(std::initializer_list<double> init)
{
for (auto i : init)
elems.push_back(i);
}
// 赋值构造函数可以接受任意父类VecExpression的实例,并且进行表达式的展开
// (对应表达式编译树中的赋值运算符节点)
template <typename E>
Vec(VecExpression<E> const &vec) : elems(vec.size())
{
for (size_t i = 0; i != vec.size(); ++i)
{
elems[i] = vec[i];
}
}
};
// 将自己作为基类模板参数的子类 - 对应表达式编译树中的二元运算符输出的内部节点
// 该结构的巧妙之处在于模板参数E1 E2可以是VecSum,从而形成VecSum<VecSum<VecSum ... > > >的嵌套结构,体现了表达式模板的精髓:将表达式计算改造成为了构造嵌套结构
template <typename E1, typename E2>
class VecSum : public VecExpression<VecSum<E1, E2>>
{
E1 const &_u;
E2 const &_v;
public:
VecSum(E1 const &u, E2 const &v) : _u(u), _v(v)
{
assert(u.size() == v.size());
}
double operator[](size_t i) const { return _u[i] + _v[i]; }
size_t size() const { return _v.size(); }
};
// 对应编译树上的二元运算符,将加法表达式构造为VecSum<VecSum... > >的嵌套结构
template <typename E1, typename E2>
VecSum<E1, E2> const operator+(E1 const &u, E2 const &v)
{
return VecSum<E1, E2>(u, v);
}
// 主函数入口
int main()
{
// 创建3个叶子节点
Vec v0 = {1.0, 1.0, 1.0};
Vec v1 = {2.0, 2.0, 2.0};
Vec v2 = {3.0, 3.0, 3.0};
auto v4 = v0 + v1; //auto 推导为VecSum<Vec, Vec> v4,这也是一个代理类
// 如果想要的不是这种类型
// 解决方案1
Vec v4 = v0 + v1;
// 解决方案2
auto v4 =static_cast<Vec>( v0 + v1);
return 0;
}