我无法理解new
关键字的正确用法。我的问题是:
delete
?#include <string>
#include <iostream>
struct myOptions {
int myInt;
std::string myString;
};
myOptions* packageOptions() {
myOptions* options = new myOptions;
options->myInt = 42;
options->myString = "hello world";
return options;
}
int main() {
myOptions* options = packageOptions();
std::cout << options->myString << std::endl;
std::cout << options->myInt << std::endl;
delete myOptions; // this just feels wrong to put here
}
我的直觉告诉我这很糟糕,因为主要功能不应该管理其他功能分配的内存,因为它打破了某种封装。我想过做一个类构造函数/解构函数,但这似乎有点矫枉过正。
答案 0 :(得分:2)
没有理由像你一样手动追逐内存。我只是在堆栈上声明你的变量,然后按值返回它。然后让RAII在变量超出范围时为您清理内存。
myOptions packageOptions() {
myOptions options;
options.myInt = 42;
options.myString = "hello world";
return options;
}
int main() {
myOptions options = packageOptions();
std::cout << options.myString << std::endl;
std::cout << options.myInt << std::endl;
}
答案 1 :(得分:1)
delete
关键字应该只出现在智能指针类的实现中。您可以按照网络建议的值返回,或者在不理想的情况下返回(例如,按值返回会导致派生类型的切片),您可以返回std::unique_ptr
并将其存储在相同的局部变量中类型,当指针超出范围时,析构函数将自动清理对象及其内存。
答案 2 :(得分:0)
使用shared_ptr
不是您目前的最佳选择。我给出了这个例子来向你展示它的存在,然后你不必费心去掉对象的删除时间。每当对象没有引用时,shared_ptr
将调用析构函数/删除,即在示例中main
的末尾。 (也是在C ++ 11中引入的shared_ptr,在C ++ 03中不可用)
#include <string>
#include <iostream>
#include <memory>
struct myOptions {
int myInt;
std::string myString;
};
using OptionsPtr = std::shared_ptr<myOptions>;
OptionsPtr packageOptions() {
OptionsPtr options = std::make_shared<myOptions>();
options->myInt = 42;
options->myString = "hello world";
return options;
}
int main() {
OptionsPtr options = packageOptions();
std::cout << options->myString << std::endl;
std::cout << options->myInt << std::endl;
}
无论如何,在你的情况下,堆栈分配,比如@Cyber答案,更可取。
答案 3 :(得分:0)
从严格的技术角度来看,你所做的很好。
但是你问过new
正确的用法是什么[在C ++中] - 答案可能让你感到惊讶。
使用new
的最佳方式是不。 delete
也是如此。您应该使用new
等智能指针以及随附的delete
,而不是使用std::shared_ptr
/ make_shared
。
我并不是说没有例外,但这些例外情况会很不寻常,通常是设计可能会被修改的结果。
事实上,我还会提出另一个问题:动态分配的正确使用是什么?同样,我建议的答案是不要使用动态分配。显然这也有例外,实际上比上面的“不使用新”指南更多例外 - 但随着你对C ++语言的语法和语义越来越有经验,你会发现动态分配在较少的情况下需要。
答案 4 :(得分:0)
不要以这种方式使用结构,而是尝试使用类和构造函数/析构函数。
答案 5 :(得分:0)
就管理内存而言,您所演示的内容是正确的。但从风格上来说,从维护的角度来看,它可能会好得多。
两种易于维护的方法是:
创建了智能指针以帮助防止内存泄漏,这在大型项目中可能是一个长期的痛苦。查看std::shared_ptr
或查看共享指针建议的答案。
传入实际结构允许调用者担心使用的内存空间,包括分配和释放它。在智能指针出现之前,这是首选方法,并且仍然是经验法则(让需要数据的代码管理与之关联的数据对象)。
传入实际结构会使代码看起来像这样:
#include <string>
#include <iostream>
struct myOptions {
int myInt;
std::string myString;
};
void packageOptions( myOptions& theInputOptions) {
theInputOptions.myInt = 42;
theInputOptions.myString = "hello world";
}
int main() {
myOptions options;
packageOptions( options );
std::cout << options.myString << std::endl;
std::cout << options.myInt << std::endl;
}
我发现这种风格更容易维护代码。它可以在需要时与智能指针结合使用。