函数值返回引用问题

小清新爱大光明 2011-11-16 09:16:35
函数1:
string make_plural(size_t ctr, const string &word, const string &ending = "s")
{
return ((1 == ctr) ? word : word + ending);
}

函数2:
const string &short(const string &s1, const string &s2)
{
return (s1.size() < s2.size() ? s1 : s2);
}

问题:
1. 函数2能返回形参的引用,而函数1为什么不能?不是说不能返回局部变量的引用嘛?
2.函数1中形参都为const string &型,为什么能返回string型而不是const string型?
...全文
210 26 打赏 收藏 转发到动态 举报
写回复
用AI写文章
26 条回复
切换为时间正序
请发表友善的回复…
发表回复
pengzhixi 2011-11-16
  • 打赏
  • 举报
回复
不是说将const string返回给string 而是通过const string构造一个string。完全是俩码事。
对象 2011-11-16
  • 打赏
  • 举报
回复
[Quote=引用 24 楼 pqpqr 的回复:]

const char *str = "hello";
char *str_b = new char[strlen(str)+ 1];
str_b = str;

为什么这里const char *不能赋值给char *? 不也是值传递么?
引用 23 楼 we_sky2008 的回复:
引用 21 楼 pqpqr 的回复:
对啊,照你所说,const型传递给非const型是unsa……
[/Quote]

你对const和pointer的理解不到位啊。

const char *str = "hello";
这个const并不是表示指针是const,而是指针指向的堆栈是const的,在这里就是hello所在的memory block是const的。
char *str_b
这种声明方式并不是指针是可读写的,而是指针所指的内存区块是可读写的.

你让str和str_b指向同一个memory block,这块数据的操作权限是read only,但是你却想让一个权限是可读写的指针指向这个内存区块,当然是错的。

按你思路,正确做法是
char *const str = "hello"; \\ this is a read only pointer
char *str_b = nullptr;
str_b = str;
把const 放到reference 操作符之后,才是表示指针是只读的。

另外这个代码段里还有个内存泄露,str_b初始化的那块内存永远也不会被释放掉。
  • 打赏
  • 举报
回复
const char *str = "hello";
char *str_b = new char[strlen(str)+ 1];
str_b = str;

为什么这里const char *不能赋值给char *? 不也是值传递么?
[Quote=引用 23 楼 we_sky2008 的回复:]
引用 21 楼 pqpqr 的回复:
对啊,照你所说,const型传递给非const型是unsafe的,那函数1为什么能将const string型值返回给string型呢?

引用 14 楼 linuxtiger 的回复:
引用 6 楼 pqpqr 的回复:

引用 2 楼 vilnies 的回复:
函数1是返回一个类型是string的临时值,string 是可以用一个 const……
[/Quote]
we_sky2008 2011-11-16
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 pqpqr 的回复:]
对啊,照你所说,const型传递给非const型是unsafe的,那函数1为什么能将const string型值返回给string型呢?

引用 14 楼 linuxtiger 的回复:
引用 6 楼 pqpqr 的回复:

引用 2 楼 vilnies 的回复:
函数1是返回一个类型是string的临时值,string 是可以用一个 const string 初始化的。所以函数1没问……
[/Quote]
构造对象时当然可以用一个const对象作为参数构造了,你看拷贝构造函数的参数是const引用的
这个和int i = 1;原理相似,1是一个int常量,你为什么不问为什么1可以用来初始化一个非const int变量呢?
对象 2011-11-16
  • 打赏
  • 举报
回复
[Quote=引用 21 楼 pqpqr 的回复:]

对啊,照你所说,const型传递给非const型是unsafe的,那函数1为什么能将const string型值返回给string型呢?
引用 14 楼 linuxtiger 的回复:
引用 6 楼 pqpqr 的回复:

引用 2 楼 vilnies 的回复:
函数1是返回一个类型是string的临时值,string 是可以用一个 const string 初始化的。所以函数1没问题……
[/Quote]

因为是值传递,你返回的是一个值,所以跟const与否无关,而我说的是引用。你可以试试返回引用的情况,返回一个const引用,但是函数是非const引用返回值类型的,看能不能通过编译,然后再试试给返回值加个const_static,再试试。
  • 打赏
  • 举报
回复
对啊,照你所说,const型传递给非const型是unsafe的,那函数1为什么能将const string型值返回给string型呢?
[Quote=引用 14 楼 linuxtiger 的回复:]
引用 6 楼 pqpqr 的回复:

引用 2 楼 vilnies 的回复:
函数1是返回一个类型是string的临时值,string 是可以用一个 const string 初始化的。所以函数1没问题。


为什么传参的时候const值不能向非const值传递呢?


const类型变量是只读变量,而非const变量是可读写变量,把一个const型引用传给非const型等于权限……
[/Quote]
FrankHB1989 2011-11-16
  • 打赏
  • 举报
回复
关于LZ的问题1L和5L的解释已经比较充分了。
但LZ还有一个误解。
什么“不能返回局部变量的引用”就是错的。
(首先,确定返回的是对象引用吧?返回函数的引用没什么必要。)
1.语法上允许。
2.为了不产生未定义行为,你需要明确你返回的引用的对象的生存期而不是作用域。正确的说法是:不要引用函数内定义的自动存储期的对象并返回。
所以,返回一个局部static对象的引用是可行的;成员函数返回一个成员的引用是可行的;返回一个对象引用类型的参数——只要参数引用的对象的生存期明确,在此时有效——的引用,也是可行的。

xingfeng2510 2011-11-16
  • 打赏
  • 举报
回复
函数1返回的是局部变量,调用拷贝构造函数;函数2返回的不是一个局部变量,返回的是一个引用,不会调用拷贝构造函数。
pengzhixi 2011-11-16
  • 打赏
  • 举报
回复
好吧,这个理由让我压力太大了,我还是不要了。
we_sky2008 2011-11-16
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 pengzhixi 的回复:]
引用 11 楼 we_sky2008 的回复:
引用 10 楼 pengzhixi 的回复:
we_sky2008,你个丫头就知道忽悠哥哥我。

不好意思,上周六周日出去玩了
哈哈

那是不是送个十字绣什么的作为道歉呢
[/Quote]
是送给我老爸的生日礼物,
一共要四个,现在我才绣了一个,所以我退了所有的QQ群专心绣绣,不然就赶不上了
对象 2011-11-16
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 pengzhixi 的回复:]

引用 11 楼 we_sky2008 的回复:
引用 10 楼 pengzhixi 的回复:
we_sky2008,你个丫头就知道忽悠哥哥我。

不好意思,上周六周日出去玩了
哈哈

那是不是送个十字绣什么的作为道歉呢
[/Quote]

你们这是在调情么。。。
对象 2011-11-16
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 pqpqr 的回复:]

引用 2 楼 vilnies 的回复:
函数1是返回一个类型是string的临时值,string 是可以用一个 const string 初始化的。所以函数1没问题。


为什么传参的时候const值不能向非const值传递呢?
[/Quote]

const类型变量是只读变量,而非const变量是可读写变量,把一个const型引用传给非const型等于权限提升,是non-type safe的,c++不允许,而把一个非const型引用传给一个const引用是可以的,因为是权限的约束,属于type safe。
pengzhixi 2011-11-16
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 we_sky2008 的回复:]
引用 10 楼 pengzhixi 的回复:
we_sky2008,你个丫头就知道忽悠哥哥我。

不好意思,上周六周日出去玩了
哈哈
[/Quote]
那是不是送个十字绣什么的作为道歉呢
teleinfor 2011-11-16
  • 打赏
  • 举报
回复
1) 函数1的写法,由于word + ending经过运算后产生了一个临时局部变量,所以不能作为引用返回,返回后这个临时局部变量就不再合法,即使你能够访问得到预期的值它也是不合法的访问方法。

2) 函数2的写法,形参的const修饰,是表明函数内部不能对传输的参数进行修改。由于s1/s2都是传递进来的阐述,所以可以返回他的引用继续使用。
we_sky2008 2011-11-16
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 pengzhixi 的回复:]
we_sky2008,你个丫头就知道忽悠哥哥我。
[/Quote]
不好意思,上周六周日出去玩了
哈哈
pengzhixi 2011-11-16
  • 打赏
  • 举报
回复
we_sky2008,你个丫头就知道忽悠哥哥我。
we_sky2008 2011-11-16
  • 打赏
  • 举报
回复
第一个word + ending是函数内部产生的临时对象,若返回它的引用,在函数调用结束后引用的将是一具尸体

第二个,因为返回的是参数,而参数类型本身就是引用,这时要分两种情况:
1.调用时是个左值,这时这个左值的生存期肯定长于该函数被调用的生命期,所以此时不会出问题
2.调用时参数是一个临时对象,此时const引用参数绑定了这个临时对象,该临时对象的生存期就是这个函数的生命期
若此时再用另外一个引用变量去接受这个函数返回结果,在函数调用结束之后,这个引用绑定到的将是一个尸体

#include<iostream>

using namespace std;

class A
{
public:
A(const char *str = "hello") : s(str)
{
}
//private:
string s;
};

const A &func(const A &ref)
{
return ref;
}


int main()
{
A a("this is ok!");
const A &ref1 = func(a);
const A &ref2 = func("this is ko!");//这里调用的时候是传递了一个临时对象

cout<<ref1.s<<endl;//这里没有问题
cout<<ref2.s<<endl;//这里是有问题的,在DEV下面没有任何显示

system("pause");
return 0;
}

zzcmx2008 2011-11-16
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 pqpqr 的回复:]
引用 2 楼 vilnies 的回复:
函数1是返回一个类型是string的临时值,string 是可以用一个 const string 初始化的。所以函数1没问题。


为什么传参的时候const值不能向非const值传递呢?
[/Quote]

因为如果参数是非const的有可能改变传入的值,但是这里只针对非const引用,如果是非引用的则无所谓,因为操作的都是实参的副本。
zzcmx2008 2011-11-16
  • 打赏
  • 举报
回复
1.函数2返回的不是一个局部变量,他返回的是传入的参数的引用。函数1不能是因为,word + ending是个临时变量,所有不能返回引用。

2.函数2的返回值是不是const string需要看你的程序的功能,要不要修改它的返回值。
  • 打赏
  • 举报
回复
[Quote=引用 2 楼 vilnies 的回复:]
函数1是返回一个类型是string的临时值,string 是可以用一个 const string 初始化的。所以函数1没问题。
[/Quote]

为什么传参的时候const值不能向非const值传递呢?
加载更多回复(5)

64,649

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧