我想定义一个函数Foo
,该函数将一些对象Widget
作为参数,该对象的数量仅在运行时知道。最简单的签名是:
void Foo(const std::vector<Widget>& widgets);
通过转换为模板并使用迭代器,可以使该函数更通用。但是,如果Widget
没有以某种连续的形式存储,则任何基于值数组的签名都将迫使调用者复制每个副本。例如,如果每个Widget
包含在其他某个对象Holder
中,或者如果仅需要对来自特异来源的3个小部件调用Foo
,则必须进行复制。如果函数接受指针 vector ,则可以避免复制:
void Foo(const std::vector<const Widget*>& widgets);
但这会使功能不安全。例如:std::vector<const Widget*> widgets;
for (const auto& holder : holders) {
widgets.push_back(&holder.get_widget());
}
Foo(widgets);
忘记const auto&
上的&符将导致段错误。我可以想到一些安全且无复制的解决方案,其中包括lambda或
Foo
模板以及自定义迭代器,但它们非常繁琐。在这种情况下最好的设计是什么?
最佳答案
The function can be made more general by turning into a template and using iterators.
这通常是一个好的设计。或者,接受通用范围。
However, if the Widgets are not stored in some contiguous form, any signature based on array-of-values would force the caller to make a copy of each.
这是使用迭代器/泛型范围而不是硬编码 vector 类型的一个很好的理由。
forgetting the ampersand on const auto& would lead to segfault.
只有幸运的时候。不能保证段故障。确实,当涉及到间接时,程序员必须小心。迭代器 vector 的另一个问题是创建新 vector 的不必要开销。
范围示例:
void Foo(const auto& widgets);
auto holder_to_widget = [](const auto& holder) {
return holder.get_widget();
};
Foo(holders | ranges::transform_view{holder_to_widget});
关于c++ - 安全地传递动态对象数组,而无需强制复制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64773921/