曲径通幽论坛

 找回密码
 立即注册
搜索
查看: 2966|回复: 0
打印 上一主题 下一主题

结构引用参数,返回结构的引用

[复制链接]

4918

主题

5880

帖子

3万

积分

GROAD

曲径通幽,安觅芳踪。

Rank: 6Rank: 6

积分
34397
跳转到指定楼层
楼主
发表于 2012-1-14 00:56:38 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
在实际应用中,引用非常适合用于结构和类,而不是普通的内置类型,如 int, double 等,对于结构的引用语法形式和其它的普通类型并没有什么区别,只要在结构名前加一个 & 即可。

下面的程序将使用结构的引用作为函数的参数,返回的也是结构的引用。

测试代码:
[C++] 纯文本查看 复制代码
#include <iostream>
using namespace std;


struct sysop {
    char name[32];
    char quote[64];
    int used;
};


const sysop &use(sysop &sysopref);


int main()
{
    sysop looper = {
        "beyes",
        "I am admin of groad.net",
        0
    };


    use(looper);      //将结构按引用传递给函数
    cout << "Looper: " << looper.used << " use(s)\n";


    sysop copycat;       //再声明一个 sysop 结构


    copycat = use(looper);        //函数的返回直接赋给 copycat 而不需要一个临时结构变量 


    cout << "Looper: " << looper.used << " use(s)\n";
    cout << "Copycat: " << copycat.used << " use(s)\n";
    cout << "use(looper): " << use(looper).used << " use(s)\n";   //通过返回直值接使用变量




    return 0;
}


const sysop &use(sysop &sysopref)
{
    cout << sysopref.name << " says:\n";
    cout << sysopref.quote << endl;


    sysopref.used++;
    
    return sysopref;
}

运行输出:
[beyes@beyes   cpp]$ ./struct_ref
beyes says:
I am admin of groad.net
Looper: 1 use(s)
beyes says:
I am admin of groad.net
Looper: 2 use(s)
Copycat: 2 use(s)
beyes says:
I am admin of groad.net
use(looper): 3 use(s)
上面程序中需要注意 3 个地方:

1. 在函数调用时,将结构 looper 按引用传递给 use() 函数,使得 sysopref 成为 looper 的别名。在 use() 函数中,在显示 sysopref 的 name 和 quote 成员时,实际上显示的是 looper 成员,同样当 ysopref.used 加 1 时实际上是 looper.used 加 1 。

2. 函数将引用作为返回值。一般情况下,返回机制是将返回值复制到一个临时存储区中,然后调用程序再去访问该区域。但是,返回引用就意味着调用程序将直接访问返回值,而不需要经过拷贝。在上面程序中, copycat = use(looper); 这个语句,如果 use() 返回的是一个普通的结构而不是引用,那么 sysopref 的内容将会被复制到一个临时的存储单元中,然后再把这个临时单元中的内容复制到 copycat 中。然而,当返回引用时,looper 的内容就直接复制到 copycat 中,中间省去了一道工序,显示出更高效率。

记住: 返回引用的函数实际上是被引用的变量的别名

3. 程序中使用了函数调用来访问结构中的成员,如语句 cout << "use(looper): " << use(looper).used << " use(s)\n"; 。这里,如果 use() 返回的是一个结构而不是结构的引用,那么这些代码访问的将是 looper 临时拷贝的 used 成员。

返回引用时需要注意的是:不能返回函数终止时不再存在的内存单元的引用。简言之,就是不能返回局部变量的引用。同样,也要避免返回指向临时变量的指针。避免这种问题的简单方法是,返回一个作为参数传递给函数的引用。换句话来说就是,函数的参数是什么引用,那么返回的就是什么的引用。还有一种方法是使用 new 来分配新的内存空间,然后返回指向该内存空间的指针,比如:
[C++] 纯文本查看 复制代码
const sysop & clone(sysop &sysopref) 
{ 
   sysop *psysop = new sysop;
   *psyop = sysopref;    //拷贝
   return *psysop;         //返回对拷贝的引用
}

上面,第一条语句创建了一个空的 sysop 结构,并将指针 psysop 指向它,所以 *psysop 解释该结构。在最后一跳返回语句中,看上去是返回该结构,但函数的声明表明,该结构实际上返回的是这个结构的引用,因此我们可以像下面这样使用该函数:
sysop &other = clone(looper);
这使得 other 成为了新结构的引用。在使用这种方法时要注意,当不需要 new 分配的内存要使用 delete 来释放它们,而调用 clone() 则隐藏了对 new 的调用,这很容易让人忘记以后用 delete 来释放内存。

此外,上面程序的返回的引用类型是 const 的,如 const sysop & 。那么 const 在此有什么用途呢?它并不意味着结构 sysop 本身就是 const ,而只是意味着不能使用返回的引用来直接修改它所指向的结构。如果省略了 const ,那么可以像下面使用代码:
use(looper).used = 10;
其等效于:
use(looper);
looper.used = 10;
还可以写下面的代码:
sysop newgal = { "xiaohang", "member of groad.net", 0};
use(looper) = newgal;
上面代码等效于:
[quote] sysop newgal =  { "xiaohang", "member of groad.net", 0};
use(looper);
looper = newgal;[/mw_shl_code]
总之,省略 const 后,可以编写更简短,但含义更模糊的代码。然而,在通常的设计中应该避免使用模糊特性,因为模糊特性增加了犯错的机会,而将返回类型声明为 const 引用,这样就避免犯糊涂了。有时,省略 const 也是有道理的,不能一概而论。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

小黑屋|手机版|Archiver|曲径通幽 ( 琼ICP备11001422号-1|公安备案:46900502000207 )

GMT+8, 2025-6-18 05:12 , Processed in 0.065810 second(s), 23 queries .

Powered by Discuz! X3.2

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表