我将介绍本地C / C ++ Meetup的lambda表达式,所以我准备了几个示例来演示lambda表达式如何解决某些任务。
其中一个示例是创建一个qsort
函数,该函数为比较函数提供lambda表达式。它适用于下面sort_ascending()
的简单情况,但对于sort_descending()
,其中我包含一个通过引用捕获的计数器整数,并且每次调用lambda表达式都会递增,我得到一个段错误首先尝试增加计数器。
我查看了我能找到的lambda表达文档,尤其是cppreference.cpp。据我所知,testcount
中的sort_descending
没有理由超出范围:testcount
与qsort_l
的调用位于同一堆栈框架中{1}},testcount
返回时,不再使用捕获qsort_l
的lambda表达式。
// -*- compile-command: "g++ -std=c++11 -ggdb -Wno-pmf-conversions -Wall -Werror -Weffc++ -pedantic -o minfail minfail.cpp" -*-
#include <stdlib.h>
#include <stdio.h>
void print_ints(const int* arr, int count)
{
for (int i=0; i<count; ++i)
{
if (i)
putchar(' ');
printf("%3d", arr[i]);
}
putchar('\n');
}
class Compar_Base
{
public:
virtual ~Compar_Base() { }
virtual int comp(const void* left, const void* right) const = 0;
static int compare(const void* left, const void* right, void* obj)
{
return static_cast<Compar_Base*>(obj)->comp(left,right);
}
};
template <typename Func>
class Compar_Concrete : public Compar_Base
{
Func &m_f;
public:
Compar_Concrete(Func f) : m_f(f) { }
virtual ~Compar_Concrete() { }
Compar_Concrete(const Compar_Concrete&) = delete;
Compar_Concrete& operator=(const Compar_Concrete&) = delete;
virtual int comp(const void* left, const void* right) const
{
return m_f(left,right);
}
};
/** Shiny, new qsort for lambda expressions. */
template <typename Func>
void qsort_l(void *base, size_t member_count, size_t member_size, Func f)
{
Compar_Concrete<Func> comp(f);
qsort_r(base, member_count, member_size, Compar_Base::compare, &comp);
}
void sort_ascending(int* intlist, int count)
{
auto f = [](const void* left, const void* right) -> int
{
return *static_cast<const int*>(left) - *static_cast<const int*>(right);
};
qsort_l(intlist, count, sizeof(int), f);
}
void sort_descending(int* intlist, int count)
{
int testcount = 0;
auto f = [&testcount](const void* left, const void* right) -> int
{
// Segmentation fault at this line:
++testcount;
return *static_cast<const int*>(right) - *static_cast<const int*>(left);
};
qsort_l(intlist, count, sizeof(int), f);
printf("\nIt took %d tests to complete the sort.\n", testcount);
}
int main(int argc, char** argv)
{
int ilist[] = {1,9,2,8,3,7,4,6,5};
int count = sizeof(ilist) / sizeof(int);
print_ints(ilist,count);
sort_ascending(ilist, count);
print_ints(ilist,count);
sort_descending(ilist, count);
print_ints(ilist,count);
}
我使用g ++版本4.8.4和5.4.0编译了上面的代码,结果相同(即段错误)。您可以通过查看代码清单顶部声明的compile-command
变量来查看正在使用的编译器选项。
答案 0 :(得分:3)
Func &m_f;
这是一个类成员,是一个参考。这是你的构造函数:
Compar_Concrete(Func f) : m_f(f) { }
m_f
成员初始化为对构造函数f
参数的引用。
不幸的是,这个参数是按值传递的。当构造函数结束并终止时,f
超出范围并被销毁,在类成员中留下悬空引用。
m_f
的后续使用最终取消引用无效引用,并导致未定义的行为。这至少是一个明显的错误。
整个代码中充满了类型不安全的通用void *
,它们可能也隐藏了一些其他错误,但是在寻找更多错误时没有意义,因为这几乎已经是表明,塞。