C++ 什么时候是';删除';对使用“新建”创建的临时对象调用?
我使用C++ 什么时候是';删除';对使用“新建”创建的临时对象调用?,c++,new-operator,delete-operator,temporary,C++,New Operator,Delete Operator,Temporary,我使用新时间(1,0,0)初始化SmartPtr类 我没有在新时间(1,0,0)上调用delete。一切正常,程序正常运行。但是我很困惑——我应该/不应该在哪里删除时间(1,0,0) 我不理解在这里创建和删除临时对象的概念。 我知道每当我在某个地方写new时,我都必须写delete! 有人能解释一下删除时间(1,0,0)发生在哪里吗 SmartPtr pTime0(新时间(0,0,1))表达式新时间(0,0,1)创建指向堆上永久对象的临时指针。临时指针确实会自动销毁(这是一个no-op),使对象
新时间(1,0,0)
初始化SmartPtr类
我没有在新时间(1,0,0)
上调用delete。一切正常,程序正常运行。但是我很困惑——我应该/不应该在哪里删除时间(1,0,0)
我不理解在这里创建和删除临时对象的概念。
我知道每当我在某个地方写new
时,我都必须写delete
!
有人能解释一下删除时间(1,0,0)发生在哪里吗
SmartPtr pTime0(新时间(0,0,1))表达式
新时间(0,0,1)
创建指向堆上永久对象的临时指针。临时指针确实会自动销毁(这是一个no-op),使对象仍在堆上,但未被引用。发生了泄漏
为防止泄漏,请确保将指针存储在某个位置,并确保最终对其调用了delete。我不知道您的
SmartPtr
类的详细信息
在任何情况下,如果您有这样的构造函数:
这是析构函数:
然后使用此代码:
泄漏时间(0,0,1)的一个实例
事实上,您还有一个new
,而不是delete
(2个new
s和1个delete
):
步骤1:调用新时间(0,0,1)
并在堆上创建一个新对象。(
new
count==1)
步骤2:将此指针传递给SmartPtr
构造函数,该构造函数深度复制以前创建的对象并在堆上分配新副本,并通过其\u指针对象
数据成员跟踪此副本。(
new
count==2)
步骤3:当SmartPtr
析构函数运行时,它delete
s由\u pointee
数据成员指向的实例,但是您泄漏了在堆上创建的第一个时间(…)
和新时间(0,0,1)
(
delete
count==1;new
count==2)
一个可能的修复方法是使用此构造函数:
SmartPtr::SmartPtr(Pointee * p)
: _pointee(p) // <--- transfer ownerhsip (no deep copies) !
{}
“时间构造函数”
字符串的总计数应与“时间析构函数”
字符串的总计数相匹配。有两种修复方法:
方法A,调用方分配,SmartPtr获得所有权:
SmartPtr::SmartPtr(Pointee * p):_pointee(p)
{
}
方法B,调用方提供内容,SmartPtr分配:
SmartPtr::SmartPtr(Pointee v):_pointee(new Pointee(std::move(v)))
{
}
析构函数保持不变:
SmartPtr::~SmartPtr()
{
delete _pointee;
}
您可以根据“永不键入新”的原则编写应用程序
将其与现有智能指针相结合,它将成为:
#include <memory> // this is where the smart-pointers live
#include "Time.h" // or whatever header defines your "Time" class
int main()
{
// note that make_shared is essentially a forwarding constructor,
// give it whatever parameters Time's constructor would take
auto p = std::make_shared<Time>(0,0,1);
// use p here
}
#include//这就是智能指针所在的位置
#包括“Time.h”//或定义“Time”类的任何标题
int main()
{
//请注意,make_shared本质上是一个转发构造函数,
//给它时间构造函数需要的任何参数
自动p=std::使_共享(0,0,1);
//这里用p
}
永远不会有任何泄漏
“永不输入新”应适用于所有应用程序编程,
唯一的例外是,如果你必须写一个低级别
资源管理图书馆
注意,如果一个类进行资源管理,它应该是
唯一的功能
所有其他课程都应遵循SmartPtr是您设计的课程吗?它可以很好地管理对象生命周期,在这种情况下,类决定何时删除。我不明白为什么要在SmartPtr的ctor中的堆上创建一个新的指针对象。这不是你想要的。您只需编写
\u pointee(p)
,即只需使用给定的相同指针。您的语句将分配一个新的指针对象,并将所提供指针的内容复制到它。我不想\u指针对象(p)
。如果p(新时间(0,0,1))在我的类之外的其他地方创建,那么它也可以在某个地方被删除(delete p
),我的SmartPtr析构函数也将delete _pointee
(由p初始化),因此它将导致运行时错误。我试图实现的概念是在ctor中分配内存,并在dtor中删除它。@Oleksandra:如果类外的代码想要删除p
本身,那么他们不会使用您的类。他们将该指针与智能指针类关联的原因是,他们希望智能指针为他们执行解除分配。调用者可以通过值传递内容,而不是作为指针,然后您可以动态分配值的副本(希望通过移动),稍后您可以释放该副本。//main.cpp SmartPtr ptTime(新时间(0,0,1));给出以下内容:时间ctor(0,0,1)SmartPtr ctor SmartPtr dtor时间dtor(0,0,1)。为什么程序不中止??如果记录时内存泄漏,也不要忘记复制构造函数。构造函数的数量(无论是复制还是默认还是其他)应该与析构函数的数量相匹配?如果是这样的话,我确实有时间构造函数、时间复制构造函数、SmartPtr构造函数、SmartPtr dtor,并且只有一个时间析构函数@Oleksandra:内存泄漏通常不会中止您的程序,它们只会使您的计算机运行得比需要的慢,而且更慢,并且sl.o.w.e…r。。。。。
SmartPtr::SmartPtr(Pointee * p)
: _pointee(p) // <--- transfer ownerhsip (no deep copies) !
{}
Time::Time(....)
{
// Do construction work....
std::cout << "Time constructor\n";
}
Time::~Time(....)
{
// Do destructor work....
std::cout << "Time destructor\n";
}
SmartPtr::SmartPtr(Pointee * p):_pointee(p)
{
}
SmartPtr::SmartPtr(Pointee v):_pointee(new Pointee(std::move(v)))
{
}
SmartPtr::~SmartPtr()
{
delete _pointee;
}
#include <memory> // this is where the smart-pointers live
#include "Time.h" // or whatever header defines your "Time" class
int main()
{
// note that make_shared is essentially a forwarding constructor,
// give it whatever parameters Time's constructor would take
auto p = std::make_shared<Time>(0,0,1);
// use p here
}