CString 是不是不可以作为返回值,请大家看一看

halleyzhang3 2013-09-19 07:15:57
有这么两个函数:
CString f1();
void f2(const cahr* p);

然后我这样用:
f2(f1());

这样是不是会有问题?在f2内部这个临时CString是不是已经销毁了呢?我想知道标准是怎么规定的,我强烈怀疑vc2008就是这么干的
...全文
695 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
melos 2013-09-22
  • 打赏
  • 举报
回复
没问题。函数返回值时,只要你不是返回地址或引用,那么返回的是一个值的副本。这里返回的是cstring对象的一个副本,当然没问题。你的出问题是,将这个副本对象里面包含的字符串地址给了一个指针,问题就出在这里,因为你没有变量去接受cstring的副本对象,它消失后你的指针无所适从。你的问题在于你把char*等同于cstring一样的对象实例,而忘了它只是一个指针,一定要指向内存中某个确定的位置。
手机打字,可能有错别字,呵呵。
unituniverse2 2013-09-21
  • 打赏
  • 举报
回复
而对于类似这样的式子: func4(func3(func2(func1()))); 别看func1在最里面func4在最外面,其实func1才是最先调用的而func4是最后调用的。所以func4才是最早退栈的。至少比func3、func2、func1都要早。
unituniverse2 2013-09-21
  • 打赏
  • 举报
回复
其实,即使撇开标准规定什么的不说,lz也可以这样理解:因为当临时变量作为函数的参数传入后,函数内部的临时变量才开始入栈与出栈。这样根据栈的后进先出的规律,函数返回前函数栈都压住了传入参数。所以只要函数不返回,参数都没有机会析构的。 至于函数的返回值,虽然对象在调用函数时还没有构造但为了保证返回的时候能有地方存同时也不影响后面的退栈,所以那块内存在函数开始调用前就会准备好(直到return语句执行时才开始调用构造函数)。
赵4老师 2013-09-21
  • 打赏
  • 举报
回复
任何类的实例都可以作为函数的返回值?
tian_shuai 2013-09-21
  • 打赏
  • 举报
回复
原因先不说,结论是CString可以当做返回值。
tian_shuai 2013-09-21
  • 打赏
  • 举报
回复
原因先不说,结论是CString可以当做返回值。
lm_whales 2013-09-20
  • 打赏
  • 举报
回复
3)返回值临时变量,本身,用完才会销毁。
lm_whales 2013-09-20
  • 打赏
  • 举报
回复
1)CString 有一个 类型转换函数 LPTSTR 2)CString内部,只有一个指针 所以,即使直接看作指针也没有问题
unituniverse2 2013-09-19
  • 打赏
  • 举报
回复
行作用域就是一整行。多少层的调用都一样。这个如果不是确定的话,右值引用什么的都不会大行其道了。

#include <iostream>
#include <conio.h>


class A1
{
public:
	A1(int) { std::cout << "construct A1" << std::endl; };
	~A1() { std::cout << "destruct A1" << std::endl; };
};

class A2
{
public:
	A2(int) { std::cout << "construct A2" << std::endl; };
	~A2() { std::cout << "destruct A2" << std::endl; };
};

class A3
{
public:
	A3(int) { std::cout << "construct A3" << std::endl; };
	~A3() { std::cout << "destruct A3" << std::endl; };
};

class A4
{
public:
	A4(int) { std::cout << "construct A4" << std::endl; };
	~A4() { std::cout << "destruct A4" << std::endl; };
};

A1 func1(void)
{
	std::cout << "func1() called." << std::endl;
	return(0);
};

A2 func2(const A1 &)
{
	std::cout << "func2() called." << std::endl;
	return(0);
};

A3 func3(const A2 &)
{
	std::cout << "func3() called." << std::endl;
	return(0);
};

A4 func4(const A3 &)
{
	std::cout << "func4() called." << std::endl;
	return(0);
};

int main(void)
{
	{
		std::cout << "-----------------start calls *1." << std::endl;
		func4(func3(func2(func1())));
		std::cout << "-----------------end calls *1." << std::endl;
	}
	{
		std::cout << "-----------------start calls *2." << std::endl;
		auto const & q = func4(func3(func2(func1())));
		std::cout << "-----------------end calls *2." << std::endl;
	}
	_getch();
	return 0;
}
执行结果:

-----------------start calls *1.
func1() called.
construct A1
func2() called.
construct A2
func3() called.
construct A3
func4() called.
construct A4
destruct A4
destruct A3
destruct A2
destruct A1
-----------------end calls *1.
-----------------start calls *2.
func1() called.
construct A1
func2() called.
construct A2
func3() called.
construct A3
func4() called.
construct A4
destruct A3
destruct A2
destruct A1
-----------------end calls *2.
destruct A4
istxy 2013-09-19
  • 打赏
  • 举报
回复
问题很简单,CString是一个类,你在函数中返回CString,而这个CString如果是你在函数内部声明的,则很可能当函数结束时这个类的实例已经没了
  • 打赏
  • 举报
回复
引用 7 楼 mougaidong 的回复:
[quote=引用 6 楼 healer_kx 的回复:] 原因先不说,结论是CString可以当做返回值。
他的问题是,这个返回值在他用的时候会不会已经释放了。[/quote] 不会,在临时变量会在这一行f2(f1());代码执行完之后才释放。
unituniverse2 2013-09-19
  • 打赏
  • 举报
回复
lz的这种问题其实就是问的临时变量的行作用域问题。 变量或类型的作用域就这几种: 静态作用域、块作用域和行作用域 行作用域中产生的所有临时对象都在离开该行时才可能*发生销毁。当然不要把行之中的函数内部的临时变量也算进去。 “可能”的具体含义是 如果外部有一个块作用域的常引用或右值引用直接引用到该对象。否则在离开行的时候就发生销毁 A func1(void); B func2(const A &); func2(func1());//行作用域。A和B都将在离开行时才销毁。在func2的作用域内部A一直有效。而B形式上将在func2 的return期间构造而在;这个点上析构。
max_min_ 2013-09-19
  • 打赏
  • 举报
回复
可以作为返回值,没有问题!
modyaj 2013-09-19
  • 打赏
  • 举报
回复
首先 Cstring 可以作为返回值 其次 楼主直接把Cstring放到了本来应该char*作为参数的参数位置 最好还是强转一下 (LPSTR)(LPCTSTR)cstring 最后 返回值在使用的时候释放的是你的临时变量吧
halleyzhang3 2013-09-19
  • 打赏
  • 举报
回复
引用 7 楼 mougaidong 的回复:
[quote=引用 6 楼 healer_kx 的回复:] 原因先不说,结论是CString可以当做返回值。
他的问题是,这个返回值在他用的时候会不会已经释放了。[/quote] 我明白了。我有这个疑问是因为首先在自己的代码里发现了
const char* psz = f();
这个错误,进而怀疑以前习以为常的CString返回值是否存在隐患,那么现在清楚了,有问题的只是上面那种用法,习以为常的返回CString是没问题的。同时也体会到MFC CString到const char*的隐式类型转换是有误导嫌疑的,还是stl::string必须用c_str()比较恰当。
引用 5 楼 mougaidong 的回复:
好好看看帖子,哪里不懂就问我,不要太着急。 你前后举这两个例子有着本质的区别。 前者,f1的返回值,在f2中被使用。这种情况下,在f2没有返回之前,f1的返回值都是有效的。 后者,在这句代码
const char* psz = f();
执行完成后就释放掉了,所以你后面再想用f()的返回值就可能会出错了。
我明白了。我有这个疑问是因为首先在自己的代码里发现了
const char* psz = f();
这个错误,进而怀疑以前习以为常的CString返回值是否存在隐患,那么现在清楚了,有问题的只是上面那种用法,习以为常的返回CString是没问题的。同时也体会到MFC CString到const char*的隐式类型转换是有误导嫌疑的,还是stl::string必须用c_str()比较恰当。谢谢了
turing-complete 2013-09-19
  • 打赏
  • 举报
回复
引用 6 楼 healer_kx 的回复:
原因先不说,结论是CString可以当做返回值。
他的问题是,这个返回值在他用的时候会不会已经释放了。
healer_kx 2013-09-19
  • 打赏
  • 举报
回复
原因先不说,结论是CString可以当做返回值。
turing-complete 2013-09-19
  • 打赏
  • 举报
回复
好好看看帖子,哪里不懂就问我,不要太着急。 你前后举这两个例子有着本质的区别。 前者,f1的返回值,在f2中被使用。这种情况下,在f2没有返回之前,f1的返回值都是有效的。 后者,在这句代码
const char* psz = f();
执行完成后就释放掉了,所以你后面再想用f()的返回值就可能会出错了。
halleyzhang3 2013-09-19
  • 打赏
  • 举报
回复
我曾经这么用过,结果好像是出了问题: 函数定义:
CString f();
使用:
const char* psz = f();
加载更多回复(2)

64,646

社区成员

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

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