让我们假设某些函数具有多个if
状态,如下面的代码所示。
这两种返回默认值的方式有什么区别?谁能告诉我这两种方法的优缺点?
第一:
CustomClass foo(const Param* par)
{
if (nullptr == par)
return CustomClass();
if (!check1(par))
return CustomClass();
if (!check2(par))
return CustomClass();
// some code
return CustomClass();
}
第二:
CustomClass foo(const Param* par)
{
CustomClass ret;
if (nullptr == par)
return ret;
if (!check1(par))
return ret;
if (!check2(par))
return ret;
// some code
return ret;
}
似乎应该取决于编译器...
答案 0 :(得分:4)
两者都是编译器优化的主题。第一个是URVO(未命名的返回值优化),第二个是NRVO(已命名的返回值优化)。 C ++标准明确允许编译器避免复制。
[12.8]
当满足某些条件时,允许实施 忽略类对象的复制/移动构造,即使 为复制/移动操作选择的构造函数和/或析构函数 因为有副作用。
...当表达式为非易失性自动对象的名称时,在具有类返回类型的函数的return语句中 (除了函数参数...以外)具有相同类型(忽略 cv-qualification)作为函数返回类型,进行复制/移动操作 可以通过将自动对象直接构造到 函数调用的返回对象
即使未启用优化,GCC,Clang和MSVC的现代版本在这两种情况下也会产生相同的汇编。以下是一些示例:
答案 1 :(得分:3)
任何明智的编译器应该为这两个函数生成相同的代码,因为它们表示的是完全相同的东西,而优化器可以相对容易地推断出这一事实。
请记住,您的源代码不是CPU指令的一对一映射:它是程序的描述。进行此描述并生成执行相同功能的最佳“实际”代码是您编译器的工作,而您的编译器则非常擅长这样做!我的意思是,无论如何,实际的已编译代码看起来几乎都不像这两个函数。
但是,最终只能通过实际检查生成的汇编代码来确定在特定平台上并使用特定实现是否确实如此。如果您只关心性能,则可以对它进行基准测试。