为啥在删除引用指向它的对象后继续存在?
Posted
技术标签:
【中文标题】为啥在删除引用指向它的对象后继续存在?【英文标题】:Why after deleting object which reference points to it continues to live?为什么在删除引用指向它的对象后继续存在? 【发布时间】:2018-10-29 11:00:34 【问题描述】:我有这样的程序:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
class no_object : public std::exception
protected:
std::string mMsg;
public:
no_object(const char* msg) : mMsg(msg)
virtual ~no_object() noexcept override
virtual const char* what() const noexcept override return mMsg.c_str();
;
using namespace std;
class Object
public:
Object(const string info) : information(info) cout << "Object constructor!" << endl;
~Object() cout << "Object destructor!" << endl;
Object(const Object& obj) information = obj.information; cout << "Copy constructor!" << endl;
void setInformation()
string getInformation() const return information;
private:
string information;
;
class Storage
public:
Storage(const size_t width)
objs = static_cast<Object*>(malloc(sizeof(Object) * width));
if (objs == NULL)
throw std::bad_alloc();
lastPointer = objs + sizeof (Object) * (width - 1);
void storeObject(Object& obj, size_t index)
if (isIndexOutOfRange(index))
throw std::out_of_range("Oops, index is out of range!");
availableIndexes.push_back(index);
objs[index] = obj;
Object& getObjectAtIndex(size_t index) const
if (isIndexOutOfRange(index))
throw std::out_of_range("Oops, index is out of range!");
auto it = find(availableIndexes.begin(), availableIndexes.end(), index);
if (it == availableIndexes.end())
throw no_object("Oops, the object for this index is not set!");
return objs[index];
~Storage()
free(objs);
private:
bool isIndexOutOfRange(size_t index) const noexcept
Object* indexPointer = objs + sizeof (Object) * index;
if (indexPointer > lastPointer)
return true;
return false;
vector<size_t> availableIndexes;
Object* objs;
Object* lastPointer;
;
int main()
Storage storage(3);
cout << "1" << endl;
Object obj = Object("lambo");
cout << "2" << endl;
Object& objRef = obj;
cout << "3" << endl;
storage.storeObject(objRef, 2);
cout << "4" << endl;
Object savedObject = storage.getObjectAtIndex(2);
cout << "Information from stored object is " << savedObject.getInformation() << endl;
return 0;
有趣的是我有下一个输出:
1
Object constructor!
2
3
Object destructor!
4
Copy constructor!
Information from stored object is lambo
Object destructor!
该程序存储对对象的引用,然后我们可以获取它们。据我所知,在删除引用指向的对象后,引用变得不可用并且它指向垃圾。
这是我的问题: 1. 我可以这样使用引用吗?安全吗? 2. 为什么要调用拷贝构造函数? 3. 我的代码是否存在其他问题? 4. 如何修正这个程序是正确的?
提前致谢。
【问题讨论】:
删除后,它在“踢足球时不允许使用双手”的意义上确实变得不可用。踢球的时候手还是可以用的,就是违反规则 下次请尝试提供MCVE。storeObject
、getObjectAtIndex
或 getObjectAtIndex
之类的东西根本与问题无关。请省略任何分散实际问题的内容
这会导致未定义的行为,这意味着任何事情都可能发生。您对行为的期望不正确
@Oleg 您确实需要在复制分配给它们之前创建这些对象(不是真的,这只是未定义的行为)。请参阅 user2079303 的答案。如果你想坚持使用malloc
,你至少应该在复制分配之前使用一个placement-new。您也可以查看std::aligned_storage
而不是malloc
。
“他没死,法官大人!他就在那儿,我可以戳他,他还有衣服、钱包和所有东西,所以他一定还活着。”
【参考方案1】:
这个程序存储对对象的引用,然后我们可以得到它们
它不存储引用。它存储对象。
我可以这样使用参考吗?安全吗?
在程序中使用引用的方式是安全的。您的任何引用都不会比被引用对象的生命周期长。
为什么要调用复制构造函数?
因为Object savedObject = storage.getObjectAtIndex(2);
是拷贝初始化。
我的代码中是否存在其他问题?
您使用malloc
分配了一块内存,而没有在内存中构造任何Object
实例。然后在objs[index] = obj;
行上,您复制分配内存中的Object
实例......除了没有Object
实例,因为您从未构造过任何实例。因此,您的程序的行为是未定义的。
另外,Storage
是不安全的,因为如果您复制它(意外或故意),它将尝试释放相同的分配两次。其行为将是未定义的。
要解决这两个问题,请使用 std::vector
而不是尝试手动内存管理。
另外,lastPointer = objs + sizeof (Object) * (width - 1);
超出了分配内存的范围。您可能忽略了指针算术通过对象大小的增量起作用的事实。在这种情况下,进一步乘以 sizeof (Object)
毫无意义。
【讨论】:
但是 Object obj = 呢?据我了解,它超出了范围,并且参考无效。 @Oleg 目前不存在对obj
的引用。以上是关于为啥在删除引用指向它的对象后继续存在?的主要内容,如果未能解决你的问题,请参考以下文章