我有这样的程序:
#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.如何正确纠正此程序?
谢谢。
答案 0 :(得分:2)
该程序存储对对象的引用,然后我们可以获取它们
它不存储引用。它存储对象。
- 我可以通过这种方式使用参考吗?安全吗?
在程序中使用引用的方式很安全。您的引用中没有一个存在超过被引用对象的生存期。
- 为什么要调用拷贝构造函数?
因为Object savedObject = storage.getObjectAtIndex(2);
是副本初始化。
- 我的代码中是否还有其他问题?
您使用malloc
分配了一块内存,而没有在内存中构造任何Object
实例。然后,在objs[index] = obj;
行上,复制-分配内存中的Object
实例...,因为没有Object
实例,因为您从未构造任何实例。因此,您的程序的行为是不确定的。
此外,Storage
是不安全的,因为如果您(无意或有意地)为其复制副本,它将尝试释放两次相同的分配。其行为将是不确定的。
要解决这两个问题,请使用std::vector
而不是尝试手动进行内存管理。
此外,lastPointer = objs + sizeof (Object) * (width - 1);
远远超出了分配的内存范围。您可能忽略了指针算术通过对象大小的增加来起作用的事实。在这种情况下,与sizeof (Object)
进一步相乘是没有意义的。