1. 返回值优化

在函数需要输出数值时,尽量使用返回值而非输出参数。因为:

  1. 前者代码直观,容易理解
  2. 前者两个操作可以在一行写出来,无需中间变量
  3. 前者性能高,没有不必要的copy
  4. 后者比较难优化

以下是返回值优化的例子。

1.1. RVO 无名返回值优化

A getA_unnamed()
{
    return A;
}

auto a = getA_unnamed();

这段代码只调用一次构造和析构,无copy和move.
可以把copy和move定义为delete,也是同样的效果。

1.2. NRVO 有名字的返回值优化

A getA_named()
{
    A a;
    return a;
}

auto a = getA_named();

这段代码只调用一次构造和析构,无copy和move.
但是,copy和move至少有一个不能被定义为delete,否则会报错。

1.3. 不确定返回值的优化

A getA_duang()
{
    A a1, a2;
    if (...)  // 编译器无法确定走哪个分支
        return a1;
    else
        return a2;
}

auto a = getA_duang();

这段代码的调用过程为:构造 - 构造 - 移动构造/拷贝构造 - 析构 - 析构 - 析构
说明:移动构造虽然没有分配堆空间,但也是构造工作,因此也有析构函数与之对应。
第三步是移动构造还是拷贝构造看实现。

2. 不能用返回值优化的场景

  1. 使用例如工厂模式这样的场景,不能返回值类型的数据,只能返回指针类型的数据。此时建议使用unique_ptrshared_ptr
  2. 移动代价很高的对象,也不适合返回值类型,此时建议:
  3. 堆上分配,然后返回对应的unique_ptr
  4. 使用非const引用作为出参
  5. 递归函数需要反复操作同一容器对象,此时建议将该容器对象作为参数,并按引用传递。

3. 其它

如果函数返回对象,那么怎样返回错误?
答:异常

results matching ""

    No results matching ""