Pet*_*ete 0 c++ containers memory-management new-operator
我一直在做一个学校作业,它大量使用向量,集合,堆栈和队列.
是什么区别Foo和Bar,传球特别是当Foo与Bar功能之间?什么时候可以安全地在Bar上调用delete?我猜测除非该向量中的所有内容都被移动delete,Bar否则永远不会安全吗?如果我返回Foo,当函数退出时,不会删除它(及其内容)吗?
vector<Line *> Foo;
Run Code Online (Sandbox Code Playgroud)
和:
vector<Line *> * Bar = new vector<Line *>();
Run Code Online (Sandbox Code Playgroud)
同样,让我说我有一个功能:
vector<Line *> BSTIndex::query(string expression)
{
vector<Line *> result; //Holds the lines that match the expression
string query = expression;
queue<string> * output = expressionParser(query);
doSomeStuffWithOutputHere();
return result;
}
Run Code Online (Sandbox Code Playgroud)
我的表达式是:
queue<string> * BSTIndex::expressionParser(string query)
{
char * cQuery = new char[100];
strcpy_s(cQuery, 100,query.c_str());
//strcpy(cQuery, query.c_str());
queue<string> * output = new queue<string>(); //Operators go in the queue
stack<string> * s = new stack<string>(); //Operands go on the stack
performSomeMagicOnQueueAndStackHere();
return output;
}
Run Code Online (Sandbox Code Playgroud)
堆栈实际上只是expressionParser的本地,所以我知道我可以从中删除新的关键字.然而,队列需要返回到使用它的查询函数,但那就是它.我是否必须在这种情况下创建指向队列的指针(我想说是,因为当expressionParser返回时它将超出范围).如果我需要创建指针,那么我应该在查询函数中调用删除输出来正确摆脱队列?
我最后一个问题是查询返回的向量.应该留下我拥有它还是它应该是一个指针,它们之间有什么区别?一旦我使用了该向量(显示其中的信息),我需要将其从内存中删除,但是,向量中包含的指针仍然很好,并且不应删除它们指向的项目.在这种情况下,最好的方法是什么?
在容器上调用delete时,容器的内容会发生什么变化?如果容器保持指针,那些指针被删除会不会影响我程序的其他区域?
所以很多问题(直接和间接)都挤进了这么小的空间!
Foo和之间有什么区别Bar.
vector<Line*> Foo;
vector<Line*>* Bar = new vector<Line*>();
Run Code Online (Sandbox Code Playgroud)
Foo是一个自动对象(可能是静态的(但这里的区别并不重要))存储持续时间.这意味着它是在声明点(被调用的构造函数)创建的,并在它超出范围(被调用的析构函数)时被销毁.
Bar另一方面是指针.指针没有构造函数或析构函数,并且用于point其他对象(或NULL).这里Bar初始化为指向动态存储持续时间的对象.这是一个必须手动释放的对象(否则会泄漏).
特别是在传递
Foo和Bar功能之间?
当Foo(通过值)传递给函数/从函数传递时,复制构造函数用于制作原始对象的副本.注意:标准明确规定可以省略从函数复制(通过返回)(查找RVO/NRVO),所有现代编译器将删除额外的复制结构并在返回站点上构建(但这是一个不可见的优化对于用户来说,只需将其视为一个非常有效的复制功能).这个的结果是,当传递给函数(通过值)或从函数返回(通过返回)时,您正在处理新对象(而不是原始对象).这很重要,因为使用对象的副作用不会影响原件.(请参阅下面关于返回的问题Foo).
传递时Bar(按值)复制指针.但这意味着指出的是相同的.因此,通过指针修改对象正在修改原始值.这使得将它作为参数传递得非常便宜(因为你传递的只是对象的地址).但它会返回一个有潜在危险的值,这是因为你可以返回一个超出函数范围的对象的地址.
在本质上危险的现代C++程序中使用指针很少直接使用RAW指针.指针通常包含在管理对象的所有权和可能寿命的对象内(请参阅智能指针和容器).
什么时候可以安全地在Bar上调用delete?
在以下情况下删除是安全的Bar:
我猜测除非该向量中的所有内容都被移动
delete,Bar否则永远不会安全吗?
Bar即使它的内容没有被移动也可以安全删除(尽管如果所包含的指针所拥有的话你可能会泄漏Bar(这不是直接不安全但是当你的空间用完时会很不方便)).这是指针很少直接使用的另一个原因,没有与指针关联的所有权语义.这意味着我们无法判断是否Bar拥有它所拥有的指针(当不再使用指针时,所有者有责任在指针上调用delete).
如果我返回
Foo,当函数退出时,不会删除它(及其内容)吗?
是.但是因为你返回一个对象,它将被复制出函数.所以你在函数之外使用的是一个副本Foo(虽然优化者可能因为RVO/NRVO而忽略了副本.如果复制被删除,则析构函数也被省略).
同样,我想说我有一个函数:query和expressionParser:
vector<Line *> BSTIndex::query(string expression)
{
vector<Line *> result; //Holds the lines that match the expression
string query = expression;
queue<string> * output = expressionParser(query);
doSomeStuffWithOutputHere();
return result;
}
queue<string> * BSTIndex::expressionParser(string query)
{
char* cQuery = new char[100];
strcpy_s(cQuery, 100,query.c_str());
queue<string> * output = new queue<string>(); //Operators go in the queue
stack<string> * s = new stack<string>(); //Operands go on the stack
performSomeMagicOnQueueAndStackHere();
return output;
}
Run Code Online (Sandbox Code Playgroud)
堆栈实际上只是expressionParser的本地,所以我知道我可以从中删除新的关键字.
你不仅可以,而且应该.目前,当它超出范围时,您正在泄漏此对象.
然而,队列需要返回到使用它的查询函数,但那就是它.我是否必须在这种情况下创建指向队列的指针(我想说是,因为当expressionParser返回时它将超出范围).
不可以.你可以通过价值来传递obejct.它将被正确复制出函数.如果您发现这很昂贵(不太可能),那么您可以使用new创建一个动态对象并将其作为指针传回(但您可能需要查看智能指针).请记住,指针并不表示您是所有者,因此不清楚谁应该删除指针(或者甚至应该删除它).所以(如果传递一个值太贵)使用std :: auto_ptr <>并将指针传回其中.
如果我需要创建指针,那么我应该在查询函数中调用删除输出来正确摆脱队列?
是.并且不.如果你创建一个dynamic object新的.然后有人必须在上面调用删除.手动执行此操作是不好的C++风格.学习使用智能指针,以便在异常安全庄园中自动完成.
我最后一个问题是查询返回的向量.应该留下我拥有它还是它应该是一个指针,它们之间有什么区别?
我会这样做:
vector<Line> BSTIndex::query(string const& expression)
{
vector<Line> result; // 1 Keep line objects not pointers.
queue<string> output = expressionParser(expression);
doSomeStuffWithOutputHere();
return result;
}
queue<string> BSTIndex::expressionParser(string const& query)
{
char cQuery[100]; // Don't dynamically allocate
// unless somebody takes ownership.
// It would probably be better to use string or vector
// depending on what you want to do.
strcpy_s(cQuery, 100, query.c_str()); // std::string can use the assignment operator.
queue<string> output; // Just build the que and use it.
stack<string> s; // Unless there is a need. Just use a local one.
performSomeMagicOnQueueAndStackHere();
return output;
}
Run Code Online (Sandbox Code Playgroud)
一旦我使用了该向量(显示其中的信息),我需要将其从内存中删除,但是,向量中包含的指针仍然很好,并且不应删除它们指向的项目.在这种情况下,最好的方法是什么?
取决于谁拥有指针.
在容器上调用delete时,容器的内容会发生什么变化?
如果容器的内容是指针.然后没事.指针消失(他们指向的是未改变且未受影响).如果容器包含对象(而不是指针),则在对象上调用析构函数.
如果容器保持指针,那些指针被删除会不会影响我程序的其他区域?
它会.但您必须手动调用删除.
| 归档时间: |
|
| 查看次数: |
438 次 |
| 最近记录: |