如何使用以下内容避免多个删除lambda:
class A {};
class B : public A {};
auto del = [](A *p) { delete static_cast<A*>(p); }
std::vector<std::unique_ptr<A, void (*)(A*)>> vec;
vec.emplace_back(new B, del); //[1]
/* OR */
vec.emplace_back(new B, [](A *p) { delete static_cast<B*>(p); }); //[2]
因此,继承B
的班级A
会被放入std::vector
std::unique_ptr<A>
个{@ 1}}并使用自定义删除工具来正确调用B
的析构函数。删除器是一个lambda,据我所知这样做:
auto l1 = []{};
auto l2 = []{};
将产生两个单独的类型,即使lambda是相同的,因为lambdas是内部的匿名struct
。上面的向量元素(unique_ptr
s)是否有办法仅对所有这些元素使用一个 lambda删除器?也许通过预先声明并将其传递给{1}},如[1]中所述?或者它与给予&#34; new&#34;几乎相同lambda用于[2]中的每个这样的调用?
答案 0 :(得分:3)
好吧,为了避免在[2]中创建很多lambdas(可能无论如何都会被优化掉),[1]是一个很好的方法,尽管每次添加新对象时都会复制lambda实例(可能也已经优化了,但我不确定)。
但是,如果你不想在每次添加std::unique_ptr
时处理传递删除器的麻烦,那就做一个仿函数:
struct deleter {
void operator()(A *p) const noexcept { delete static_cast<B*(p); }
};
因为deleter
是DefaultConstructible,std::unique_ptr
的构造函数可以自己创建一个删除对象,而不必传递一个。使用lambdas是不可能的,因为它们不是DefaultConstructible。
答案 1 :(得分:1)
构造函数将删除器复制到每个unique_ptr
。使用lambda做什么并不重要,每个unique_ptr
对象都会有一个副本。
另外,我建议不要将删除器的类型作为函数指针。而是使用lambda的decltype
来避免间接调用。会为你节省一些性能。此外,非捕获lambda可能会为unique_ptr
占用0个字节的存储空间,而函数指针将为您拥有的每个sizeof(void*)
占用unique_ptr
。