假设您有一个全局类(例如可用于应用程序的运行时)
class MyClass {
protected:
std::string m_Value;
public:
MyClass () : m_Value("hello") {}
std::string value() { return m_Value; }
};
MyClass v1;
当我做
时,使用第一个表单会给我带来奇怪的行为printf("value: %s\n", v1.value().c_str());
看起来字符串在printf可以使用之前从内存中消失了。 有时它打印值:hello其他时候它会崩溃或什么都不打印。
如果我第一次复制字符串
std::string copiedString = v1.value();
printf("value: %s\n", copiedString.c_str());
事情确实有效。
当然必须有办法避免使用临时字符串。
编辑:所以共识是使用const std :: string&返回值。
我知道每个人都说原始代码应该没问题,但我可以告诉你 我在Windows CE上看到MSVC 2005遇到了麻烦,但仅限于CE盒子。不是Win32交叉编译。
答案 0 :(得分:6)
您的代码应该可以正常运行。还有其他错误,我们无法从这个测试用例中检测到。也许通过valgrind运行你的可执行文件来搜索内存错误。
答案 1 :(得分:1)
嗯,代码没有任何问题(正如我所解释的那样)。它不是最优的,肯定不是The Right Way (R)
,你应该像villentehaspam建议的那样修改你的代码。就像现在一样,你的代码会复制字符串m_value
,因为你按值返回,这不如只返回一个const引用。
如果您提供显示问题的完整代码示例,我可以帮助您更好。
答案 2 :(得分:0)
并不重要但是该类中的std :: string返回可以使用const其他方面你只是创建一个成员值的副本,这是一种浪费。
std::string value() const { return m_value; }
答案 3 :(得分:-1)
以下是您撰写时通常会发生的事情:
printf("value: %s\n", v1.value().c_str());
std::string
保留从v1.value()
返回的值。v1.value()
并将其返回值放在临时字符串中(具体如何改变它:通常它会将对临时的引用传递给方法的隐藏参数。请参阅{{3}讨论)。.c_str()
上调用std::string
,它会在某处隐藏const char *
结果(例如注册)。std::string
,因此将其销毁(即调用其析构函数,可能会释放一些堆栈空间)。const char *
指针作为printf()
的参数传递。问题是第3步中的指针指向临时std::string
分配的内存,当调用临时析构函数时,它会被释放。到printf()
使用时,这段记忆可能会很久没有了。
基本上,任何类似于您所显示的用法都是危险的,应该避免使用。使用以下内容是正确的:
std::string copiedString = v1.value();
printf("value: %s\n", copiedString.c_str());
因为copiedString
的析构函数在copiedString
超出范围之后才被调用,printf()
返回后的某个时间。实际上,这并不比v1.value().c_str()
效率低,因为在任何一种情况下都会创建一个临时的std::string
。
返回对字符串的引用是一个很好的选择,只要调用者需要它,引用仍然有效。因此,对长期存在的对象中的成员变量的引用是可以的;对某些事物的提及结果是暂时的不是。