这些函数是 Qt Concurrent 框架的一部分。
QtConcurrent::map ()、 QtConcurrent::mapped ()和 QtConcurrent::mappedReduced ()函数在一个序列(例如 QList 或 QVector )中的各个条目上并行地进行运算。 QtConcurrent::map ()会原地修改该序列, QtConcurrent::mapped ()会返回一个包含修改后的数据的新序列,而 QtConcurrent::mappedReduced ()会返回一个单个的结果。
以上的每个函数都有一个阻塞模式的变种,会返回最终结果而不是一个 QFuture 。妳可以像使用那些异步模式的变种一样地使用它们。
QList < QImage > images = ...;
//以下每个调用都会阻塞,直到整个操作结束
QList < QImage > future = QtConcurrent ::blockingMapped(images, scaled);
QtConcurrent ::blockingMap(images, scale);
QImage collage = QtConcurrent ::blockingMappedReduced(images, scaled, addToCollage);
注意,以上示例中的结果的类型不是 QFuture 对象,而是真正的结果类型(在以上例子中,分别是 QList < QImage >和 QImage )。
QtConcurrent::mapped ()需要传入一个输入序列和一个映射函数。这个映射函数会被针对序列中的每个条目调用一次,然后会返回一个新的序列,其中包含的是那些由映射函数返回的值。
映射函数必须是这样的形式:
U function(const T &t);
T和U可以是任意类型(它们甚至可以是同一类型),但是T必须符合序列中储存的条目的类型。这个函数返回的是修改过的、或者说是映射过的内容。
以下示例演示的是如何对一个序列中的所有条目应用缩放函数:
QImage scaled(const QImage &image)
{
return image.scaled(100, 100);
}
QList < QImage > images = ...;
QFuture < QImage > thumbnails = QtConcurrent ::mapped(images, scaled);
映射的结果是储存在 QFuture 中的。参考 QFuture 和 QFutureWatcher 的文档,以了解如何在妳的程序中使用 QFuture 。
如果妳想原地修改一个序列,那么就使用 QtConcurrent::map ()。映射函数必须是这样的形式:
U function(T &t);
注意,映射函数的返回值和返回类型是无用的。
使用 QtConcurrent::map ()跟使用 QtConcurrent::mapped ()是类似的:
void scale( QImage &image)
{
image = image.scaled(100, 100);
}
QList < QImage > images = ...;
QFuture < void > future = QtConcurrent ::map(images, scale);
由于这个序列是原地修改的,所以 QtConcurrent::map ()不通过 QFuture 返回任何值。然而,妳仍然可以使用 QFuture 和 QFutureWatcher 来跟踪这个映射过程的状态。
QtConcurrent::mappedReduced ()与 QtConcurrent::mapped ()是类似的,但它不是返回一个包含新的结果的序列,而是使用一个归并函数来将这些结果组合到一个单独的返回值中。
归并函数必须是以下的形式:
V function(T &result, const U &intermediate)
T是最终结果的类型,U是映射函数的返回类型。注意,归并函数的返回值和返回类型是无用的。
像这样调用 QtConcurrent::mappedReduced ():
void addToCollage( QImage &collage, const QImage &thumbnail)
{
QPainter p(&collage);
static QPoint offset = QPoint (0, 0);
p.drawImage(offset, thumbnail);
offset += ...;
}
QList < QImage > images = ...;
QFuture < QImage > collage = QtConcurrent ::mappedReduced(images, scaled, addToCollage);
对于映射函数返回的每个结果,都会调用一次归并函数,而归并函数应当将 intermediate 合并到 result 变量中去。 QtConcurrent::mappedReduced ()确保了每一时刻都只会有一个线程调用归并函数,所以无需使用一个互斥锁来锁住结果变量。 QtConcurrent::ReduceOptions 枚举还使得妳可以控制归并的顺序。如果指定的是 QtConcurrent::UnorderedReduce (默认值),那么归并就是无序的,而指定 QtConcurrent::OrderedReduce 的话就可以确保归并是按照原来的序列中的顺序进行的。
以上每个函数都有一个以迭代器范围代替序列参数的变种。它们用起来与使用序列参数的变种是一样的:
QList < QImage > images = ...;
QFuture < QImage > thumbnails = QtConcurrent ::mapped(images.constBegin(), images.constEnd(), scaled);
//原地映射只支持非常量的迭代器
QFuture < void > future = QtConcurrent ::map(images.begin(), images.end(), scale);
QFuture < QImage > collage = QtConcurrent ::mappedReduced(images.constBegin(), images.constEnd(), scaled, addToCollage);
以上每个函数都有一个阻塞模式的变种,它们返回最终结果,而不是一个 QFuture 对象。用起来也与异步模式的变种是一样的:
QList < QImage > images = ...;
//以下每个调用都是阻塞的,直到整个操作完成
QList < QImage > future = QtConcurrent ::blockingMapped(images, scaled);
QtConcurrent ::blockingMap(images, scale);
QImage collage = QtConcurrent ::blockingMappedReduced(images, scaled, addToCollage);
注意,以上示例中的结果的类型不是 QFuture 对象,而是真正的结果类型(在以上例子中,分别是 QList < QImage >和 QImage )。
QtConcurrent::map ()、 QtConcurrent::mapped ()和 QtConcurrent::mappedReduced ()允许使用成员函数的指针。所用的成员函数的类类型必须符合序列中储存的条目的类型:
//对一个QStringList中的所有字符串执行紧缩操作
QStringList strings = ...;
QFuture < void > squeezedStrings = QtConcurrent ::map(strings, & QString ::squeeze);
//对一个图片列表中的每张图片,交换其所有像素的rgb 值
QList < QImage > images = ...;
QFuture < QImage > bgrImages = QtConcurrent ::mapped(images, & QImage ::rgbSwapped);
//创建一个集合,其中包含的是一个字符串列表中所有字符串的长度
QStringList strings = ...;
QFuture < QSet < int > > wordLengths = QtConcurrent ::mappedReduced(string, & QString ::length, & QSet < int >::insert);
注意,在使用 QtConcurrent::mappedReduced ()的时候,妳可以自由地组合使用普通函数和成员函数:
//可以在使用QtConcurrent::mappedReduced()的时候将普通函数和成员函数自由组合
//计算一个字符串列表中的字符串的平均长度
extern void computeAverage( int &average, int length);
QStringList strings = ...;
QFuture < int > averageWordLength = QtConcurrent ::mappedReduced(strings, & QString ::length, computeAverage);
//创建一个集合,其中包含的是一个图片列表中所有图片里出现过的颜色
extern int colorDistribution(const QImage &string);
QList < QImage > images = ...;
QFuture < QSet < int > > totalColorDistribution = QtConcurrent ::mappedReduced(images, colorDistribution, QSet < int >::insert);
QtConcurrent::map ()、 QtConcurrent::mapped ()和 QtConcurrent::mappedReduced ()允许使用函数对象,利用这一点可以在函数调用中加入状态信息。必须使用result_type 这个类型别名(typedef)来定义该函数调用操作符的结果类型:
struct Scaled
{
Scaled( int size)
: m_size(size) { }
typedef QImage result_type;
QImage operator()(const QImage &image)
{
return image.scaled(m_size, m_size);
}
int m_size;
};
QList < QImage > images = ...;
QFuture < QImage > thumbnails = QtConcurrent ::mapped(images, Scaled(100));
注意,Qt 不提供对绑定函数的支持。这个功能是由第三方库提供的,例如 Boost 或 C++ TR1库扩展 。
如果妳想使用一个需要多于一个参数的映射函数,那么妳可以使用boost::bind()或std::tr1::bind()来将它转换成一个只需要一个参数的函数。
举个例子,我们要使用 QImage::scaledToWidth ():
QImage QImage ::scaledToWidth( int width, Qt ::TransformationMode) const;
scaledToWidth需要3个参数(包括“this”指针),无法直接用在 QtConcurrent::mapped ()中,因为 QtConcurrent::mapped ()需要一个只有一个参数的函数。要想在 QtConcurrent::mapped ()中使用 QImage::scaledToWidth ()的话,我们需要提供一个宽度( width )值和变换( transformation )模式:
boost::bind(& QImage ::scaledToWidth, 100, Qt ::SmoothTransformation)
boost::bind()的返回值是一个拥有以下特征(signature)的函数对象(函子(functor)):
QImage scaledToWith(const QImage &image)
这就满足了 QtConcurrent::mapped ()的要求,以下是完整的示例:
QList < QImage > images = ...;
QFuture < QImage > thumbnails = QtConcurrent ::mapped(images, boost::bind(& QImage ::scaledToWidth, 100 Qt ::SmoothTransformation));
HxLauncher: Launch Android applications by voice commands