如何设置一个 std::vector 与另一个,其中两个是不同类的向量?
How to set an std::vector with another one, where the two are vectors of different classes?
有没有办法用另一个设置一个std::vector,其中两者是不同类的向量?
struct A {
int a;
};
struct B {
int a, b;
B(int _a, int _b) : a(_a), b(_b) {}
};
int commonB = 123;
std::vector<A> va;
std::vector<B> vb;
// Fill va...
// Code I would like to optimise:
for(size_t i = 0; i < va.size(); ++i) {
vb.push_back(B(va[i].a, commonB));
}
类似(伪代码(的任何内容:
vb = va;
B::b 值未初始化?
我只想指出,自从基于范围的 for 循环以来,我并没有太多想要经常使用像 transform 这样的简单算法。我希望你能明白为什么。
std::transform(va.begin(), va.end(), std::back_inserter(vb),
[commonB](A x) -> B { return B(x.a, commonB); });
for (auto& e : va)
vb.emplace_back(e.a, commonB);
来自<algorithm>
标头的transform
与来自<iterator>
的back_inserter
一起可用于使它像这样:
std::transform(va.begin(), va.end(), std::back_inserter(vb),
[](A x) -> B { return B(x.a, commonB); });
更新
如果commonB
没有全局作用域,则应捕获其名称(写在 lambda 定义的方括号中(:
std::transform(va.begin(), va.end(), std::back_inserter(vb),
[commonB](A x) -> B { return B(x.a, commonB); });
您可以使用转换函数和 lambda 进行泛化。
当您使用 -O2 或更好的编译时,所有这些都将得到完美优化:
请注意,在矢量增长时,使用reserve()
来防止重新分配。
#include <vector>
#include <algorithm>
struct A {
int a;
};
struct B {
int a, b;
B(int _a, int _b) : a(_a), b(_b) {}
};
template<class TransformFunction>
std::vector<B> transform_copy(std::vector<A>& source, TransformFunction&& trans)
{
std::vector<B> result;
result.reserve(source.size());
std::transform(source.begin(), source.end(), std::back_inserter(result), trans);
return result;
}
int main()
{
int commonB = 123;
auto transform_function = [commonB](A const& source) {
return B(source.a, commonB);
};
std::vector<A> va;
std::vector<B> vb = transform_copy(va, transform_function);
}
您还可以使其更具表现力。Lambdas是一种简单且最有效的表达人类可读概念的方式,如惰性函数(如Haskell等(:
auto vb = transform_to_Bs(va, with_common_b(123));
可以这样实现:
#include <vector>
#include <algorithm>
struct A {
int a;
};
struct B {
int a, b;
B(int _a, int _b) : a(_a), b(_b) {}
};
extern std::vector<A> get_As();
int main() {
auto with_common_b = [](auto &&commonB) {
return [commonB](auto &&a) {
return B(a.a, commonB);
};
};
auto transform_to = [](auto &&target, auto &&source, auto &&transform_function) {
target.reserve(source.size());
std::transform(source.begin(), source.end(),
std::back_inserter(target),
std::forward<decltype(transform_function)>(transform_function));
};
auto transform_to_Bs = [transform_to](auto &&va, auto &&transform_function) {
std::vector<B> result;
transform_to(result, va, std::forward<decltype(transform_function)>(transform_function));
return result;
};
std::vector<A> va = get_As();
auto vb = transform_to_Bs(va, with_common_b(123));
}
在这里应用完美的转发是一种严重的过度优化。编译器实际上将消除函数对象的所有冗余副本。
我认为你不能得到更优化的。您可以确保预先vb
保留足够的空间以避免不必要的重新分配,并使用基于范围的 for 循环和emplace_back
使循环更加简洁:
vb.reserve(va.size());
for (const auto& a : va)
vb.emplace_back(a, commonB);
相关文章:
- 如何在C++中从两个单独的for循环中添加两个数组
- 为什么两个不同的未命名名称空间可以共存于一个cpp文件中
- 当在同一名称空间中有两个具有相同签名的函数时,会发生什么
- 如何返回一个类的两个对象相加的结果
- 如何在C++中将一个无符号的 int 转换为两个无符号的短裤?
- 如何设置一个 std::vector 与另一个,其中两个是不同类的向量?
- 从两个不同类继承的非虚拟基类的访问成员
- 使用转换运算符相互转换两个不同类的对象
- 两个不同类的运行时多态性
- 如何比较两个不同类的对象
- 具有两个不同类的两个不同构造函数
- 如何在具有相同基类的两个不同类中获取向量
- 两个不同类的泛型函数
- 检查来自不同类的两个Rect之间的冲突
- c++中包含两个不同类的对象的列表
- 比较来自两个不同类的对象
- c++ Boost信号连接模板中两个不同类的两个函数
- 等同c++中来自不同类的两个对象
- 重载指向两个不同类的指针的赋值运算符
- 如何锁定由属于两个不同类的两个线程修改的数据结构