当我不再需要使用一个在堆上分配的std::string时,最好的删除方式是什么?谢谢!
当我不再需要使用一个在堆上分配的std::string时,最好的删除方式是什么?谢谢!
std::string
只是一个普通的类1,因此通常的规则也适用。
如果你在栈上、全局变量或类成员中分配std::string
对象,你不需要进行任何特别的操作。当它们超出作用域时,析构函数会被调用,并自动释放用于字符串的内存。
int MyUselessFunction()
{
std::string mystring="Just a string.";
// ...
return 42;
// no need to do anything, mystring goes out of scope and everything is cleaned up automatically
}
你只有在使用 new
运算符在堆上分配一个std::string
对象时才需要处理;在这种情况下,就像使用 new
分配的任何对象一样,你必须调用delete
释放它。
int MyUselessFunction()
{
// for some reason you feel the need to allocate that string on the heap
std::string * mystring= new std::string("Just a string.");
// ...
// deallocate it - notice that in the real world you'd use a smart pointer
delete mystring;
return 42;
}
正如这个例子所暗示的,通常情况下在堆上分配std::string
是没有意义的,即使需要这样做,仍应该将指针封装在智能指针中,以避免甚至出现内存泄漏的风险(例如在异常情况、多个返回路径等情况下)。
实际上,std::string
被定义为
namespace std
{
typedef std::basic_string<char> string;
};
所以它是basic_string
模板类用于字符类型char
的实例化的同义词(这不会改变答案,但在Stack Overflow上,即使在新手问题上,你也必须很严谨)。
std::basic_string<char>
是一种模板特化,typedef
为其创建了一个同义词;既然他说他懂C,我认为typedef
的作用应该很明显;不过还是进行了修正,下次请随意进行编辑。 - Matteo Italiatemplate<>
语法的显式专业化或部分显式专业化。结果证明并非如此,对于误导性评论我感到抱歉。 - Sergei Tachenovstring aaa
,然后在某个时刻将其设置为某个值 aaa = string("长字符串,例如文件内容......")
。如果我再次进行赋值操作会发生什么?(即再次执行 aaa = string("另一个长字符串"
)?第一个字符串是否会自动从堆中释放? - Mike Keskinovaaa
;在赋值时,aaa
的先前内容会自动释放,而(现在为空的)临时字符串将在表达式结束时销毁。请注意,不涉及临时变量的赋值行为略有不同(目标字符串的存储被回收以容纳新内容,而不是被释放,因此即使大于必要的容量,它也将保留现有容量),但您永远不会冒任何内存泄漏的风险:当std::string
被销毁时,其内存会被释放。 - Matteo Italiastd::string foo("since it's on the stack, it will auto delete out of scope");
或:
std::string* foo = new std::string("allocated on the heap needs explicit destruction")
delete foo;
如果变量在堆上,使用delete
释放;如果变量在栈上,则无需释放。
std::string
的分配,您需要以下内容:std::string str;
// fill str with 250 chars
str.clear(); // clears the content: size = 0, capacity = 250
str.shrink_to_fit(); // shrinks the capacity: size = 0, capacity = 16 or 22 (depends on implementation)
void foo() {
string* myString = new string("heap-allocated objects are deleted on 'delete myString;'");
cout << *myString << endl;
delete myString;
}
或者更好的方法是尽可能避免使用指针,而是使用自动变量:
void foo() {
string myString("stack-allocated string is automatically deleted when myString goes out of scope");
cout << myString << endl;
}
也许你正在处理释放内部字符串缓冲区的问题?
出于性能原因,大多数实现都会保留内部缓冲区的分配,即使字符串已经“清空”。此外:小字符串(小于sizeof(ptr)
)直接存储在保存指针的区域中。这些字节在字符串的生命周期内永远无法被回收。
要释放内部资源:经典的技巧是在作用域内使用swap
。这将强制缓冲区真正释放(也适用于vector
/map
/ostream
/stringstream
等...):
string s; // size==0 and capacity==15 as the default proxy of the container (help perf on small string)
s = "Looooooooooooooooooooooooooooooong String"; // size==41 and capacity==47 bytes allocated
s.clear(); // size==0 BUT capacity==47 bytes STILL allocated!!
s = "Looooooooooooooooooooooooooooooong String"; // size==41 and capacity reuse 47 bytes still allocated.
s.resize(0); // size==0 BUT capacity==47 bytes STILL allocated!!
// swap with scope to force freeing string internals
{
string o;
o.swap(s);
} // size==0 AND capacity==15 (back to smallest footprint possible)
s = "12345"; // size==5 AND capacity==15 (the string is IN the container, no new alloc)
只需将std :: string视为任何基本类型即可。
std::string *str = new std::string("whatever");
///code
delete str;
您可以像对待其他类一样处理std::string
。使用new
进行分配,完成后使用delete
释放。
在C++11中,我不建议在大多数情况下使用new
和delete
。如果需要在堆上分配字符串,请使用std::shared_ptr进行包装:
std::shared_ptr<std::string> my_string = std::make_shared<std::string>(std::string("My string"));
一旦所有my_string
的副本超出范围,相关内存将自动删除。
std::shared_ptr
的存在是为了提供优雅的代理共享所有权语义和自动引用计数,而不是为了使堆分配更容易。然而,std::unique_ptr
是完全不同的故事。在建议使用任何一个之前,提到使用两者的影响可能是明智的... - Mateusz Grzejek