压平地图中的向量
flatten vectors in a map
在 C++ 中,我有一个 map < int, vector < double > >
或 map < int, vector < some_Struct > >
,我需要连接此映射中的向量和 return 结果。
第一版函数如下:
#include <algorithm>
#include <vector>
vector < double >
flattenRecords(const map < int, vector < double > > & selected, int num_kept_reps)
{
vector < double > records;
int cnt = 0;
for (auto it = selected.begin(); it != selected.end(); ++it) {
records.insert(records.end(),
make_move_iterator(it->second.begin()),
make_move_iterator(it->second.end()));
cnt += 1;
if (cnt >= num_kept_reps)
break;
}
return records;
}
我知道这不是我打算做的,因为我想把数据保存在map
,因此不应该使用make_move_iterator
。
代码可以使用带有 -std=c++0x
标志的 g++ (GCC) 4.4.7 编译。
所以问题来了,我将 map
声明为 const
,当我尝试对 vector
使用 std::move
时会发生什么map
?
我的第二个版本是使用:
copy(it->second.begin(), it->second.end(), back_inserter(records));
我想这正是我想要做的。
我对 C++ 很陌生。 STL给我的感觉是python所以我想试试
如果您不想移动元素,请不要使用 make_move_iterator(Iterator),只需使用 Iterator。例如:
records.insert(records.end(), it->second.begin(), it->second.end());
如您所料,您的第二个版本确实实现了您想要实现的目标。
关于您关于 const 映射上的 std::move 的问题,std::move 在这种情况下不会做任何事情。由于 std::move 是无条件转换为右值的,它会将元素转换为对右值的 const 引用。因为它是 const 它将匹配左值 ctor(在这种情况下是复制 ctor),而不是移动(复制)ctor。
例如:
const std::string s1 = "Test";
const std::string s2 = std::move(s1);
这将调用 std::string 的复制构造函数,而不是移动构造函数。因此,它会复制,而不是移动。
这会做一个动作:
std::string s1 = "Test";
const std::string s2 = std::move(s1);
两个示例中的 s2 参数不必是常量。 copy/move.
没有区别
有一个 'pythonic' 替代方案,如果您来自 Python,您可能会喜欢它,使用 lambda 和 "mapped-reduce" 函数
std::vector<double> merged = std::accumulate(selected.begin(),
selected.end(),
std::vector<double>(),
[](const std::vector<double>& a, std::vector<double>& b)
{
std::vector<double> result(a);
std::copy(b.begin(), b.end(), std::back_inserter(result));
return result;
});
);
std::move
实际上并没有移动数据。它将引用强制转换为右值引用,如果非 const,则为移动构造函数可以使用的 "movable" 数据类型。但它永远不会删除 const 类型限定符,因此在 const 引用上使用 std::move
不会将其转换为可移动类型。
在 C++ 中,我有一个 map < int, vector < double > >
或 map < int, vector < some_Struct > >
,我需要连接此映射中的向量和 return 结果。
第一版函数如下:
#include <algorithm>
#include <vector>
vector < double >
flattenRecords(const map < int, vector < double > > & selected, int num_kept_reps)
{
vector < double > records;
int cnt = 0;
for (auto it = selected.begin(); it != selected.end(); ++it) {
records.insert(records.end(),
make_move_iterator(it->second.begin()),
make_move_iterator(it->second.end()));
cnt += 1;
if (cnt >= num_kept_reps)
break;
}
return records;
}
我知道这不是我打算做的,因为我想把数据保存在map
,因此不应该使用make_move_iterator
。
代码可以使用带有 -std=c++0x
标志的 g++ (GCC) 4.4.7 编译。
所以问题来了,我将 map
声明为 const
,当我尝试对 vector
使用 std::move
时会发生什么map
?
我的第二个版本是使用:
copy(it->second.begin(), it->second.end(), back_inserter(records));
我想这正是我想要做的。
我对 C++ 很陌生。 STL给我的感觉是python所以我想试试
如果您不想移动元素,请不要使用 make_move_iterator(Iterator),只需使用 Iterator。例如:
records.insert(records.end(), it->second.begin(), it->second.end());
如您所料,您的第二个版本确实实现了您想要实现的目标。 关于您关于 const 映射上的 std::move 的问题,std::move 在这种情况下不会做任何事情。由于 std::move 是无条件转换为右值的,它会将元素转换为对右值的 const 引用。因为它是 const 它将匹配左值 ctor(在这种情况下是复制 ctor),而不是移动(复制)ctor。
例如:
const std::string s1 = "Test";
const std::string s2 = std::move(s1);
这将调用 std::string 的复制构造函数,而不是移动构造函数。因此,它会复制,而不是移动。
这会做一个动作:
std::string s1 = "Test";
const std::string s2 = std::move(s1);
两个示例中的 s2 参数不必是常量。 copy/move.
没有区别有一个 'pythonic' 替代方案,如果您来自 Python,您可能会喜欢它,使用 lambda 和 "mapped-reduce" 函数
std::vector<double> merged = std::accumulate(selected.begin(),
selected.end(),
std::vector<double>(),
[](const std::vector<double>& a, std::vector<double>& b)
{
std::vector<double> result(a);
std::copy(b.begin(), b.end(), std::back_inserter(result));
return result;
});
);
std::move
实际上并没有移动数据。它将引用强制转换为右值引用,如果非 const,则为移动构造函数可以使用的 "movable" 数据类型。但它永远不会删除 const 类型限定符,因此在 const 引用上使用 std::move
不会将其转换为可移动类型。