什么" int& FOO()"用C ++表示?

时间:2016-04-07 13:23:20

标签: c++ function return-by-reference

在左值和左值上阅读this explanation时,这些代码行向我伸出:

int& foo();
foo() = 42; // OK, foo() is an lvalue

我在g ++中尝试过,但编译器说"未定义引用foo()"。如果我添加

int foo()
{
  return 2;
}

int main()
{
  int& foo();
  foo() = 42;
}

它编译得很好,但运行它会产生segmentation fault。只是一行

int& foo();

单独编译并运行没有任何问题。

这段代码是什么意思?如何为函数调用赋值,为什么它不是rvalue?

9 个答案:

答案 0 :(得分:164)

解释假设foo有一些合理的实现,它返回对有效int的左值引用。

这样的实现可能是:

int a = 2; //global variable, lives until program termination

int& foo() {
    return a;
} 

现在,由于foo返回左值引用,我们可以为返回值赋值,如下所示:

foo() = 42;

这将使用值a更新全局42,我们可以直接访问变量或再次调用foo来检查:

int main() {
    foo() = 42;
    std::cout << a;     //prints 42
    std::cout << foo(); //also prints 42
}

答案 1 :(得分:67)

所有其他答案在函数内声明静态。我想这可能会让你感到困惑,所以看看这个:

int& highest(int  & i, int  & j)
{
    if (i > j)
    {
        return i;
    }
    return j;
}

int main()
{
    int a{ 3};
    int b{ 4 };
    highest(a, b) = 11;
    return 0;
}

因为highest()返回引用,您可以为其分配值。运行时,b将更改为11.如果更改了初始化以使a为8,那么a将更改为11.这是一些代码,与其他例子不同,它实际上可能有用。

答案 2 :(得分:31)

Add

声明一个名为foo的函数,它返回对command.Parameters.Add(new SqlParameter("@data", SqlDbType.DateTime) {Value = date}); 的引用。这个例子没有做的是给你一个你可以编译的函数的定义。如果我们使用

int& foo();

现在我们有一个函数返回对int的引用。因为bar是int & foo() { static int bar = 0; return bar; } ,它将在调用函数后继续运行,因此返回对它的引用是安全的。现在,如果我们做

bar

我们分配42到static会发生什么,因为我们分配了引用,而引用只是foo() = 42; 的别名。如果我们再次调用该函数,如

bar

因为我们将bar设置为上面的内容,所以会打印42。

答案 3 :(得分:14)

int &foo();声明一个名为foo()的函数,返回类型为int&。如果在不提供正文的情况下调用此函数,则可能会出现未定义的引用错误。

在第二次尝试中,您提供了一个功能int foo()。这与int& foo();声明的函数具有不同的返回类型。因此,您有两个相同的foo声明不匹配,这违反了一个定义规则导致未定义的行为(无需诊断)。

对于有效的东西,取出本地函数声明。如您所见,它们可能导致无声的未定义行为。相反,只在任何函数之外使用函数声明。您的程序可能如下所示:

int &foo()
{
    static int i = 2;
    return i;
}  

int main()
{
    ++foo();  
    std::cout << foo() << '\n';
}

答案 4 :(得分:10)

int& foo();是一个返回对int的引用的函数。您提供的函数返回int而不引用。

你可以做

int& foo()
{
    static int i = 42;
    return i;
}

int main()
{
    int& foo();
    foo() = 42;
}

答案 5 :(得分:7)

int & foo();表示foo()返回对变量的引用。

考虑以下代码:

#include <iostream>
int k = 0;

int &foo()
{
    return k;
}

int main(int argc,char **argv)
{
    k = 4;
    foo() = 5;
    std::cout << "k=" << k << "\n";
    return 0;
}

此代码打印:

$ ./a.out    K = 5

因为foo()返回对全局变量k的引用。

在修订后的代码中,您将返回的值转换为引用,然后该引用无效。

答案 6 :(得分:5)

在这种情况下,&amp;表示引用 - 所以foo返回对int的引用,而不是int。

我不确定你是否使用过指针,但这是一个类似的想法,你实际上并没有从函数中返回值 - 而是你传递了找到位置所需的信息int所在的内存。

总而言之,您没有为函数调用赋值 - 您正在使用函数来获取引用,然后将引用的值赋给新值。很容易认为一切都在同一时间发生,但实际上计算机会按照精确的顺序完成所有事情。

如果你想知道 - 你得到段错误的原因是因为你正在返回一个数字文字'2' - 所以如果你要定义一个const int然后尝试它就是你得到的确切错误修改其价值。

如果你还没有学过指针和动态记忆,那么我建议首先考虑一些我认为难以理解的概念,除非你一次性学习它们。

答案 7 :(得分:4)

链接页面上的示例代码只是一个虚函数声明。它不会编译,但是如果你定义了一些函数,它通常会起作用。这个例子意味着&#34;如果你有一个带有这个签名的函数,你就可以像那样使用#34;。

在您的示例中,foo显然是根据签名返回左值,但您返回一个转换为左值的右值。这显然决定失败。你可以这样做:

int& foo()
{
    static int x;
    return x;
}

并且在说:

时改变x的值会成功
foo() = 10;

答案 8 :(得分:3)

你拥有的函数foo()是一个返回对整数的引用的函数。

所以,让我们说foo最初返回5,之后,在你的主函数中,你说<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer" p:location="/WEB-INF/jdbc.properties"/> <bean id="dataSource" class="com.rss.setting.RoutingDataSource"> <property name="targetDataSources"> <map key-type="com.rss.setting.DbType"> <entry key="MASTERS" value-ref="dataSourceMaster"/> <entry key="TARIFF" value-ref="dataSourceTariff"/> <entry key="SETTING" value-ref="dataSourceSetting"/> </map> </property> <property name="defaultTargetDataSource" ref="dataSourceMaster"/> </bean> <bean id="dataSourceMaster" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> <bean id="dataSourceTariff" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.usernameTarif}"/> <property name="password" value="${jdbc.passwordTarif}"/> </bean> <bean id="dataSourceSetting" class="org.apache.commons.dbcp.BasicDataSource"> <property name="url" value="${jdbc.url}" /> <property name="username" value="${jdbc.usernameSetting}"/> <property name="password" value="${jdbc.passwordSetting}"/> </bean> <context:property-placeholder location="/WEB-INF/jdbc.properties"/> <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource"> <ref bean="dataSource"/> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.OracleDialect</prop> <prop key="hibernate.show_sql">false</prop> <prop key="hibernate.hbm2ddl.auto">update</prop> <prop key="format_sql">true</prop> </props> </property> </bean> ,然后输出foo,它将打印10而不是5。

我希望这是有道理的:)

我也是编程新手。有趣的是看到这样的问题让你思考! :)