C ++:从void函数

时间:2016-05-03 16:38:58

标签: c++ coding-style standards-compliance

我有几个void函数(让我们称之为foo和bar),它们共享相同的void函数清理,如果它们搞砸了,那么它们会在它们之后清理:

#include <iostream>

void cleanup() { std::cout << "doing cleanup" << std::endl; }

void foo(int & i) {
    if(i == 0) { return cleanup(); }
    --i;
    if(i == 0) { return cleanup(); }
    ++i;
}

void bar(int & i) {
    if(i == 0) { return cleanup(); }
    ++i;
    if(i == 0) { return cleanup(); }
    --i;
}

int main() {
    int i = 0;
    foo(i);
    bar(i);
    return 0;
}

cpp.sh愉快地编译并运行代码。

感谢the answer to this question我知道我可以返回void类型的对象。但我不知道它是否适用于返回空值返回值。

您如何看待代码是否符合标准?

您是否宁愿返回虚拟整数以使代码更具可读性?或者无用的返回值会使代码难以阅读吗?

编辑:我觉得我需要添加一些说明,例如为什么&#39;清理();返回;&#39;不是解决方案。实际代码比示例更复杂,并且取决于我离开函数的位置,在cleanup()调用之后会发生其他一些事情。 &#39;返回清理();&#39;在我可以/必须立即离开的情况下,只是一种方便的方法,不会将所有东西放在条件中。

4 个答案:

答案 0 :(得分:5)

来自n4582

6.6.3返回语句[stmt.return]

第2段

  

return语句的expr-or-braced-init-list称为其操作数。不带操作数的return语句只能用于返回类型为cv void的函数,构造函数(12.1)或析构函数(12.4)。 具有void类型的操作数的return语句只能在返回类型为cv void的函数中使用。具有任何其他操作数的return语句只能在返回类型不是cv的函数中使用无效; return语句初始化要从操作数复制初始化(8.5)返回的对象或引用。

问题:

  

但我不知道它是否适用于返回的返回值。

是的,从返回void的函数返回void表达式是完全有效的。这在模板化代码中变得非常方便,因此您不必使用特殊情况的void函数。

  

您如何看待代码是否符合标准?

是绝对的。

  

您是否宁愿返回虚拟整数以使代码更具可读性?或者无用的返回值会使代码难以阅读吗?

这完全取决于你和你的美学。它是否使代码看起来更具可读性(或者您是否需要遵循编码指南)。就个人而言,我不会返回虚拟值(因为用户可能期望从中获得某些意义)。

答案 1 :(得分:2)

这对于完美转发非常有用。想象一下,你有一个类型(模板参数)的仿函数,所以返回类型可能是任何东西。这种返回类型void值的权限允许您调用函子并将其返回值公开给调用者,而不必为没有返回值的情况编写单独的代码。

template<typename Functor, typename... Args>
auto forward(Functor what_to_call, Args... args) -> decltype(what_to_call(std::forward<Args>(args)...))
{
    return what_to_call(std::forward<Args>(args)...);
}

这已经非常混乱了,但如果没有使用return关键字传播void返回类型的能力,那么您需要两个由enable_if控制的变体。

template<typename Functor, typename... Args>
auto forward(Functor what_to_call, Args... args) -> enable_if<is_same_type<decltype(what_to_call(std::forward<Args>(args)...)), void>::value, void>::type
{
    what_to_call(std::forward<Args>(args)...);
    return;
}

template<typename Functor, typename... Args>
auto forward(Functor what_to_call, Args... args) -> enable_if<!is_same_type<decltype(what_to_call(std::forward<Args>(args)...)), void>::value, decltype(what_to_call(std::forward<Args>(args)...))>::type
{
    return what_to_call(std::forward<Args>(args)...);
}

因此,return function_returning_void();是针对有用的特殊情况而设计的。不要觉得你必须返回类型为void的虚拟对象或任何其他类型的虚拟对象,因为它是可能的。例如,只需return void();即可完成return -1;return;

答案 2 :(得分:2)

  

您如何看待代码是否符合标准?

是的,确实如此。在返回void的函数中,如果表达式的类型为void,则可以在return语句中使用表达式。它是什么,如果它是对函数的调用也返回void

  

您是否宁愿返回虚拟整数以使代码更具可读性?或者无用的返回值会使代码难以阅读吗?

我不认为虚拟整数会使代码更具可读性。程序员期望返回值有意义。

我认为更具可读性的是分割函数调用和返回单独的语句:

cleanup();
return;

虽然我承认,这完全是一个意见问题。

答案 3 :(得分:0)

如果一个函数没有返回任何值,那么检查函数是否成功完成它必须做的事情会更明智。一个小例子:

        bool foo()
        {
        if (DoSomeThing() == true)
        {
            return true;
        }
        else
        {
            return false;
        }

然后你可以返回foo()的返回值:

        if (!foo())
        {
            Console.WriteLine("foo returned false!");
        }