c++ - 关于不要返回局部对象的引用或指针的疑问 ? //c primer中文版 201页

浏览:56日期:2023-05-07

问题描述

1问题

c++primer中文版201页说函数不能返回局部对象的指针或引用。

const string &manip(){ string ret; if(!ret.empty())return ret; //错误返回局部对象的引用 else return 'empty'; //错误 “empty”是一个局部临时量 }

我在essential c++看到了这样的代码,函数可以返回局部变量的char 指针 和const char *,这是为什么呢?(在win7 + vs2010下编译通过并可以运行打印'num_sequence')

#include <iostream>#include <string>using namespace std; class num_sequence{ public:virtual const char *what_am_i( ) const// 返回值char * 和const char*可以编译通过{ return 'num_sequence';} }; int main() {num_sequence p;std::cout<<p.what_am_i(); }2进一步提问

把函数返回值有const char改为char 也可以编译通过,但不能通过char指针修改字符串的内容。

virtual char *what_am_i( ) const//把函数返回值有const char*改为char *也可以编译通过 {return 'num_sequence'; }

问题2我好像了解了,类似于char* p= “safdsaf”;也是不能通过指针修改rodata里的内容的。

3 希望有人帮我解释下,标题1 的内容。

问题解答

回答1:

const string &manip(){ string ret; if(!ret.empty())return ret; //错误返回局部对象的引用 else return 'empty'; //错误 “empty”是一个局部临时量 }

上面两个都是返回的临时变量(return 'empty'先构建一个临时的string,再返回),在函数调用结束的时候就**析构了。所以是不安全的。编译是可以通过的,但是对于返回的结果,因为已经析构,所以是不应该使用的。

virtual const char *what_am_i( ) const// 返回值char * 和const char*可以编译通过{ return 'num_sequence';}

上面返回的是一个指针,指向字符串'num_sequence',这个字符串是在全局静态区,是一直存在的,不是临时的,所以没有问题。

对于问题2

实际上是不论返回的是char*还是const char*你都是不能修改的,因为其指向的是一个常量字符串。强行修改会在运行时报错。

回答2:

楼上回答的也比较清楚了,你需要了解下进程的内存布局。一般认为进程的内存布局包括的区域有:1)代码区2)文字常量区3) 全局区/静态区4) 堆区5) 栈区 可参见 http://blog.csdn.net/duyiwuer2009/article/details/7994091所以,你看下面的例子,只要引用的是常量区的字符串相同,那么他们的地址值就是一样的,而不是构建一个对象。

#include <stdio.h>#include <string>using std::string;void foo(){ char * a = (char*)'hello world'; printf('%pn', a);;}void foo2(){ const char * b = 'hello world'; printf('%pn', b);}int main(){ foo(); foo2(); return 0;}

我的电脑上输出

0x1004030310x100403031

而对于你的问题1,

const string &manip(){ string ret; if(!ret.empty())return ret; //错误返回局部对象的引用 else return 'empty'; //错误 “empty”是一个局部临时量 }

因为返回类型是一个常量引用,而返回的实际值是一个常量字符串,在这个过程中会先构造一个临时变量,内容为'empty',类型为string,然后再返回给调用者,返回的过程中,这个临时变量就被释放了,你继续访问有可能访问成功,也可能不成功,但不管怎么样,数据已经是一个脏数据了,这种行为C++没有规定一定是程序崩溃或不崩溃,统一称为未定义的行为,由运行上下文来定,是否崩溃。

相关文章: