当我取消引用指针并将值分配给某个变量时,内存会发生啥?
Posted
技术标签:
【中文标题】当我取消引用指针并将值分配给某个变量时,内存会发生啥?【英文标题】:What happens to memory when I dereference a pointer and assign the value to some variable?当我取消引用指针并将值分配给某个变量时,内存会发生什么? 【发布时间】:2013-09-19 19:25:09 【问题描述】:我有一个具有私有字符串指针的类。此类还有一个公共方法,该方法取消引用该字符串指针并将结果字符串返回给调用者。我的问题是:保存取消引用的字符串的内存会发生什么?
这是我的代码:
#include <iostream>
#include <string>
class myclass
private:
std::string *_name;
public:
myclass()
this->_name = new std::string("my name");
~myclass()
delete this->_name;
std::string getName()
return *this->_name;
;
void main()
myclass m;
std::string str = m.getName(); //what happens to this memory?
std::cout << str << std::endl;
//str deleted here (I think)
//here, the m._name pointer hasn't yet been deleted
在我的主函数中,变量str
被分配了取消引用的字符串。保存这个字符串的内存会发生什么?我认为内存保留在堆栈上,因此当变量超出范围时会自动“取消分配”。令我困惑的是,即使取消引用的字符串不再在范围内,私有字符串指针仍可能在范围内。是否为 str
变量分配了私有 _name
指针值的副本?
如果这段代码确实在后台复制了字符串,我是否应该关注性能。如果我只是让getName()
返回_name
指针而不取消引用它,我的代码会运行得更快吗?
【问题讨论】:
它显然被复制了..如果您返回私有变量的地址,您将暴露它以被任何外部程序更改。我认为这不是您要在这里寻找的东西..std::string getName()
正在返回一个字符串的副本。 str
值从_name
指向的字符串副本中复制值。更好的方法是将 getName() 定义为 const std::string& getName() const return *(this->_name);
取消引用和解除分配是两件不同的事情:前者我们访问指针指向的内存位置,后者我们释放该特定变量的内存。
离题,但您可能不希望将指向字符串的指针作为成员。直接使用字符串。
@user2023861 getName() 没有释放任何东西,您在函数中取消引用字符串然后返回字符串的副本。然后将此副本再次复制到 str 中。返回带有 & 的字符串会导致它返回对 *_name
的引用而不进行复制,然后它将被复制到 str
中。它是const
的原因是为了不破坏封装。如果不是 const,您将可以直接访问 _name
指向的私有成员变量,这可能是您想要的,但它与您当前的 getName()
实现不同。
【参考方案1】:
首先,您不需要指针。其次,你可以返回一个副本(就像你做的那样)或一个引用(如果你想坚持的话,也可以返回一个指针),但是这两种方法都有利有弊:
class myclass
private:
std::string _name;
public:
myclass() : _name("my name")
std::string getName1() return _name;
std::string& getName2() return _name;
const std::string& getName3() const return _name;
getName1
按值返回。缺点是会生成一个副本,这会影响性能,但在对象超出范围后返回值可以安全使用。
getName2
和getName3
的区别在于可以使用前者来修改类的实际成员。缺点是如果对象超出范围,则无法再使用该引用,因此您将留下一个悬空引用。优点是它更高效,因为不涉及复制。
myclass x;
std::string a = x.getName1(); // copy is made
std::string& b = x.getName2(); // no copy
// b is mutable
b = "something else"; //this will modify x._name
const std::string& c = x.getName3; // no copy
// c is const
myclass* y = new myclass;
std::string d = x.getName1(); // copy is made
std::string& e = x.getName2(); // no copy
delete y;
d = "something else"; //legal
e = "something else"; //undefined behavior, e is a dangling reference
【讨论】:
如果我这样做std::string str2 = m->getName2();
,(没有与号),str2 会是副本吗?在我的测试中,str2 似乎在delete y
之后仍然存在。
@user2023861 是的,它是副本。【参考方案2】:
遵循“三法则”。如果您定义了以下任何一个:复制构造函数、赋值运算符、析构函数,则定义所有这些。这样就不会混淆指向字符串的指针是否被删除:您只需在相应的赋值运算符中创建一个新的。
【讨论】:
以上是关于当我取消引用指针并将值分配给某个变量时,内存会发生啥?的主要内容,如果未能解决你的问题,请参考以下文章
当我们在 C 中取消引用 NULL 指针时,操作系统会发生啥?