指针 vs 引用并清理它
Pointers vs references and cleaning it all up
考虑这段代码:
#include <iostream>
using namespace std;
struct SOME_OTHER_BASE {
// members
};
struct FOO : SOME_OTHER_BASE {
int value;
static FOO *CreatePtr(int param)
{
FOO *res = new FOO();
res->value = param;
return res;
}
static FOO &CreateRef(int param)
{
return *CreatePtr(param);
}
};
int main() {
FOO *ptr = FOO::CreatePtr(2);
FOO &ref = FOO::CreateRef(4);
FOO local = FOO::CreateRef(5);
cout << "ptr: " << ptr->value << endl;
cout << "ref: " << ref.value << endl;
cout << "local: " << local.value << endl;
delete ptr;
delete &ref;
return 0;
要求:
- FOO::CreatePtr 方法在某些情况下可能 return NULL(分配失败并被处理,参数无效等)
- FOO 是 POD,但不是聚合
我想要的:尽可能少的删除调用(和内存泄漏)。
我的观察:
- 我可以使用 FOO::CreatePtr,检查
NULL
,然后总是 delete
- 我可以使用 FOO::CreateRef,但我无法真正检查 null,我仍然必须
delete
- 当
CreatePtr
是 NULL
时,我可以使 FOO::CreateRef
return 成为一个特殊实例。这将有助于 NULL 检查,但仍然无助于删除。
- 我可以使用本地变体,但我认为我那里有内存泄漏(
CreatePtr(5)
永远不会被删除,只会被复制到 local
中)
- 这是非常低效的,因为有一个不必要的分配和一个副本
- 我不能使用大括号初始化,因为 FOO 不是聚合
有什么方法可以声明 FOO 类型的局部变量并在声明中对其进行初始化,以便在函数退出时自动将其删除?
不确定是否应该为您的情况使用指针。
此外,您并没有删除为 local
变量创建的指针。
因为 FOO
应该是一个 POD 并且取决于它的大小(这取决于 SOME_OTHER_BASE
的大小),你可以 return 它通过你的创建方法的值:
struct FOO : SOME_OTHER_BASE {
int value;
static FOO Create(int param) {
FOO foo;
foo.value = param;
return foo;
}
};
int main() {
FOO local = FOO::Create(2);
FOO &ref = local;
FOO *ptr = new FOO(FOO::Create(6));
// can check if ptr is NULL if you want
cout << "local: " << local.value << endl;
cout << "ref: " << ref.value << endl;
cout << "ptr: " << ptr->value << endl;
delete ptr;
return 0;
}
如果无法创建您的对象,则抛出异常。无论如何,它更有用,因为它提供了更多无法创建对象的上下文,并允许程序修复问题。您还避免了 delete
的问题,因为您不使用 new
。如果要以多态方式使用该类型,则需要使用 std::unique_ptr
或 std::shared_ptr
.
等智能指针
#include <iostream>
#include <stdexcept>
using namespace std;
struct SOME_OTHER_BASE {
// members
};
struct CreationFailure : std::runtime_error
{
CreationFailure(const std::string& s) :
std::runtime_error(s)
{
}
};
struct FOO : SOME_OTHER_BASE {
int value;
FOO(int value) :
SOME_OTHER_BASE(), // pass the constructor arguments
value(value)
{
// additional actions
if(/* creation failed */)
throw CreationFailure("out of memory");
}
};
int main() {
FOO local(2);
cout << local.value << endl;
return 0;
}
如果不能添加构造函数,同样的逻辑可以移到工厂函数中:
FOO createFoo(int v)
{
FOO f;
f.value = v;
if(/* creation failed */)
throw CreationFailure("out of memory");
return f;
}
考虑这段代码:
#include <iostream>
using namespace std;
struct SOME_OTHER_BASE {
// members
};
struct FOO : SOME_OTHER_BASE {
int value;
static FOO *CreatePtr(int param)
{
FOO *res = new FOO();
res->value = param;
return res;
}
static FOO &CreateRef(int param)
{
return *CreatePtr(param);
}
};
int main() {
FOO *ptr = FOO::CreatePtr(2);
FOO &ref = FOO::CreateRef(4);
FOO local = FOO::CreateRef(5);
cout << "ptr: " << ptr->value << endl;
cout << "ref: " << ref.value << endl;
cout << "local: " << local.value << endl;
delete ptr;
delete &ref;
return 0;
要求:
- FOO::CreatePtr 方法在某些情况下可能 return NULL(分配失败并被处理,参数无效等)
- FOO 是 POD,但不是聚合
我想要的:尽可能少的删除调用(和内存泄漏)。
我的观察:
- 我可以使用 FOO::CreatePtr,检查
NULL
,然后总是delete
- 我可以使用 FOO::CreateRef,但我无法真正检查 null,我仍然必须
delete
- 当
CreatePtr
是NULL
时,我可以使FOO::CreateRef
return 成为一个特殊实例。这将有助于 NULL 检查,但仍然无助于删除。
- 当
- 我可以使用本地变体,但我认为我那里有内存泄漏(
CreatePtr(5)
永远不会被删除,只会被复制到local
中)- 这是非常低效的,因为有一个不必要的分配和一个副本
- 我不能使用大括号初始化,因为 FOO 不是聚合
有什么方法可以声明 FOO 类型的局部变量并在声明中对其进行初始化,以便在函数退出时自动将其删除?
不确定是否应该为您的情况使用指针。
此外,您并没有删除为 local
变量创建的指针。
因为 FOO
应该是一个 POD 并且取决于它的大小(这取决于 SOME_OTHER_BASE
的大小),你可以 return 它通过你的创建方法的值:
struct FOO : SOME_OTHER_BASE {
int value;
static FOO Create(int param) {
FOO foo;
foo.value = param;
return foo;
}
};
int main() {
FOO local = FOO::Create(2);
FOO &ref = local;
FOO *ptr = new FOO(FOO::Create(6));
// can check if ptr is NULL if you want
cout << "local: " << local.value << endl;
cout << "ref: " << ref.value << endl;
cout << "ptr: " << ptr->value << endl;
delete ptr;
return 0;
}
如果无法创建您的对象,则抛出异常。无论如何,它更有用,因为它提供了更多无法创建对象的上下文,并允许程序修复问题。您还避免了 delete
的问题,因为您不使用 new
。如果要以多态方式使用该类型,则需要使用 std::unique_ptr
或 std::shared_ptr
.
#include <iostream>
#include <stdexcept>
using namespace std;
struct SOME_OTHER_BASE {
// members
};
struct CreationFailure : std::runtime_error
{
CreationFailure(const std::string& s) :
std::runtime_error(s)
{
}
};
struct FOO : SOME_OTHER_BASE {
int value;
FOO(int value) :
SOME_OTHER_BASE(), // pass the constructor arguments
value(value)
{
// additional actions
if(/* creation failed */)
throw CreationFailure("out of memory");
}
};
int main() {
FOO local(2);
cout << local.value << endl;
return 0;
}
如果不能添加构造函数,同样的逻辑可以移到工厂函数中:
FOO createFoo(int v)
{
FOO f;
f.value = v;
if(/* creation failed */)
throw CreationFailure("out of memory");
return f;
}