我有一个util函数,可以返回地图
std::map getFooMap() {
std::map foo;
// ... populate the map
return foo;
}
从调用者那边,我想将地图分配给某个对象的数据字段。我可以的:
dest.data = getFooMap()
这会比以下速度更快吗?
auto temp = getFooMap();
dest.data = std::move(temp);
我认为应该避免复制一份吗?
答案 0 :(得分:2)
我认为应该避免复制一份吗?
只要“ std::map
”是可移动的,您就只能避免一个额外的移动-优化程序也可以避免该移动。
性能差异可能微不足道或根本不存在,但是dest.data = getFooMap()
更简单并且可能不会更慢。
正如评论中指出的那样,直接初始化dest.data
而不是在构造之后进行分配会更快。这可以通过在成员初始化程序中调用getFooMap
来实现。
答案 1 :(得分:1)
从美学的角度来看,它是第一个变种。您必须对语言标准和编译器作者有一定的信心,以免像临时工具那样愚蠢的工件来促进优化。
让我们检查是否确实如此。首先,让我稍微抽象一下您的示例,并将map
替换为类foo
,而无需定义其各种方法;并假设没有抛出任何异常:
#include <utility>
// Originally this was an std::map, replaced with
// an "opaque" class to shorten the output and
// prevent inlining and conflation of
// std-map-related code with the rest of the code
struct foo {
foo() noexcept;
foo(const foo&) noexcept;
foo(foo&&) noexcept;
foo& operator=(foo&&) noexcept;
foo& operator=(const foo&) noexcept;
~foo() noexcept;
};
struct dest_t { foo data; };
foo get_foo() noexcept;
void do_stuff_with(const dest_t& dest) noexcept;
void move_from_intermediate() noexcept {
dest_t dest;
auto temp = get_foo();
dest.data = std::move(temp);
do_stuff_with(dest);
}
void straight_assignment() noexcept {
dest_t dest;
dest.data = get_foo();
do_stuff_with(dest);
}
现在,如果我们compile this on GodBolt,我们将看到GCC(主干)为两个函数产生相同的汇编代码。其中包括:
get_foo()
的电话do_stuff_with()
的电话。 clang(trunk)也将产生相同的代码,直到稍微重新排序-但与GCC并不完全相同。