我希望以下代码失败(在main
函数中),但它有效:
class Response {
public:
Response() {}
void displayInfo() {
cout << "Hello!" << endl;
}
};
class HttpClient
{
public:
HttpClient(Response& response) : m_response(&response) {
m_response = &response;
}
Response* getResponse() {
return m_response;
}
private:
Response *m_response;
};
HttpClient* createClient()
{
Response response;
HttpClient *clnt = new HttpClient(response);
clnt->getResponse()->displayInfo();
return clnt;
}
int main()
{
HttpClient* client = createClient();
// ------------------------------------------
// I expect getResponse()->displayInfo() to fail, since "response" object
// passed as argument to HttpClient (in createClient function) goes out of the scope and should be deleted.
client->getResponse()->displayInfo();
}
所以我在response
函数中创建了局部变量createClient
。
然后将此局部变量作为构造函数参数(引用)传递给HttpClient。
此参数已分配给成员Response *m_response
。
据我了解,m_response
保留对response
局部变量的引用。
但是当response
局部变量超出范围时,我仍然可以通过m_response
(m_response
对象的调用方法)访问它。
我希望m_response
引用一些垃圾,因为response
超出范围。
为什么会这样?
答案 0 :(得分:2)
为什么会这样?
它的工作原理基本上是因为实现允许它,可能是因为它还没有重用/回收局部变量正在使用的内存。这里的行为是未定义的,所以任何事情都可能发生。它可以像这样工作,但它没有。
此外,当您访问现在已经消失的内存指针时,我最好定义“失败”的含义。通常,C ++标准中存在强大且较弱的“失败”保证。强故障保证是明确定义的(例如,抛出异常,返回错误代码)。但是有很多弱的故障最终会导致在编写代码时必须小心的未定义行为。许多指针操作失败最终都是未定义的行为,所以如果你想要更强的失败保证,我会切换到智能指针等。