如果涉及委托,C++ 中的 RVO 和查询结果作为对象或更好地通过引用传递
RVO in c++ and Query result as object or better pass by reference, if delegation is involved
我必须决定 return 使用对象查询的结果或通过引用传递给它们。查询将至少被委托一次。如果我 return 一个对象并进一步委托它,是否有编译器 RVO。这是一个例子:
struct foo {int a, b, c, d;}
struct b {
Foo foo() {Foo foo; /*calculate_with_foo;*/ return foo;}
void foo1(Foo& foo) { /*calculate_with_foo;*/ }
}
struct delegator {
Foo foo() {return b.foo();}
void foo1(Foo& foo) {b.foo1(foo);}
b b;
}
// Performes this slower or is here RVO at work?
delegator d;
foo result = d.foo()
// pass by reference, faster?
foo resultr;
d.foo1(resultr);
复制省略号 can be chained。所以是的,RVO 可以应用于 delegator::foo
,NRVO 可以应用于 b::foo
,并且可以链接这些优化,这样就不需要进行复制。
此外,在这种情况下,由于所有函数都很简单且可内联,优化器甚至可以为两个调用生成相同的输出。
总的来说,两者都很快。具体的,你应该衡量一下。
按值返回的优点是使用起来更简单,因为不需要单独的行来分配变量。此外,它允许您不关心返回的类型而只使用 auto
- 不过您是否想要是个人喜好。
在不适用于您的代码的更一般情况下,按值返回允许类型不可默认构造。避免默认构造无论如何都会被修改的对象可以节省一些开销。
我必须决定 return 使用对象查询的结果或通过引用传递给它们。查询将至少被委托一次。如果我 return 一个对象并进一步委托它,是否有编译器 RVO。这是一个例子:
struct foo {int a, b, c, d;}
struct b {
Foo foo() {Foo foo; /*calculate_with_foo;*/ return foo;}
void foo1(Foo& foo) { /*calculate_with_foo;*/ }
}
struct delegator {
Foo foo() {return b.foo();}
void foo1(Foo& foo) {b.foo1(foo);}
b b;
}
// Performes this slower or is here RVO at work?
delegator d;
foo result = d.foo()
// pass by reference, faster?
foo resultr;
d.foo1(resultr);
复制省略号 can be chained。所以是的,RVO 可以应用于 delegator::foo
,NRVO 可以应用于 b::foo
,并且可以链接这些优化,这样就不需要进行复制。
此外,在这种情况下,由于所有函数都很简单且可内联,优化器甚至可以为两个调用生成相同的输出。
总的来说,两者都很快。具体的,你应该衡量一下。
按值返回的优点是使用起来更简单,因为不需要单独的行来分配变量。此外,它允许您不关心返回的类型而只使用 auto
- 不过您是否想要是个人喜好。
在不适用于您的代码的更一般情况下,按值返回允许类型不可默认构造。避免默认构造无论如何都会被修改的对象可以节省一些开销。