C ++:引用为返回值

时间:2011-04-15 15:08:06

标签: c++ function reference return-value

我注意到当我意外忘记从应该返回引用的函数返回时,我没有得到任何编译器错误。我写了一些小测试来看看实际发生了什么,我比任何事情都更加困惑。

struct Foo
{
    int x;

    Foo() {
        x = 3;
    }
};

Foo* foo = new Foo;

Foo& test(bool flag) {
    if (flag)
        return *foo;
}

如果 test()没有(显式地)返回值,我仍然会返回一些内容。但是,返回的 Foo 对象未使用默认构造函数进行初始化 - 这是因为 x 与非显式返回值中的3不同。

当您不返回引用时实际发生了什么?如果这是一个特性,那么在发生错误时使用它作为返回虚拟对象的方法是安全的,而不是返回空指针。 (见下面的例子。)

class FooFactory
{
    // Return reference...

    Foo& createFooRef() {
        Foo* foo = new Foo;
        bool success = foo->load();

        if (success)
            return *foo;
        // Implicit (and safe?) return value on failure?
    }

    // ... as opposed to returning a pointer.

    Foo* createFooPtr() {
         Foo* foo = new foo;
         bool success = foo->load();

         if (success)
             return foo;
         else
             return 0;
    }

    // Yes, I am aware of the memory leaks,
    // but that's not the point of the example.

6 个答案:

答案 0 :(得分:3)

大多数编译器会向您发出警告,但您可能需要提高编译器的警告级别才能看到它。

不,这不安全。这是坏的。它可能会导致堆栈损坏,只需返回当时堆栈上发生的任何事情。正如您已经看到的那样,为您使用构造函数。如果你想要一个默认的构造对象,你必须自己做(但要注意返回对临时对象的引用。这也很糟糕)。

答案 1 :(得分:2)

降低编译器中引用的常用方法是指针。对于引用返回函数,它意味着您将获得表示的任意地址,无论用于返回值的寄存器或堆栈槽中是什么。

在语言中,效果未定义。

答案 2 :(得分:2)

这是未定义的行为,可能会发生无限的坏事,或者实际上可能不会发生,或者有时可能发生,或者可能同时发生,如果它不喜欢你,或者将工程师从Microsoft派到你家用棒球棒击败你的头部。

答案 3 :(得分:1)

所描述的行为不仅限于返回引用的函数。以下代码也将编译:
 int func1( int i )
{
if( i )
return 3; // C4715 warning, nothing returned if i == 0
}

我不确定他们为什么只生成一个warning,而不是一个错误(设置中可能有一个选项可以将其变为错误),但是如果调用这样的函数,你将得到未定义的行为

答案 4 :(得分:1)

引用通常只是指针的语法糖,因此返回将从堆栈中获取返回值的指针值。如果你不给它它只会抓垃圾。

我必须使用该函数,然后添加-Wall以使g ++抱怨:

g ++ -Wall foo.cc foo.cc:在成员函数'Foo& FooFactory :: createFooRef()': foo.cc:19:警告:控件到达非空函数的结尾

答案 5 :(得分:0)

您是否尝试使用/ O1优化或更高版本进行编译并将警告视为错误?那可能会失败。我记得在GCC 4.1中发生的那些事情。您可能忘记在调试模式下返回引用,但引用将返回;只要你对它进行任何优化,它仍然会编译,但不会返回引用。在文本编辑器中进行编码时(就像我那时那样),这对我来说是一种彻底的痛苦和巨大的惊喜。