C++ 新的,然后加入C++;建造师?

C++ 新的,然后加入C++;建造师?,c++,constructor,new-operator,throw,C++,Constructor,New Operator,Throw,如果我这样做 新的是否被合理分配std::string释放?我想可能是因为没有调用析构函数 我使用的不是std::string,而是我自己的类,只是将其作为一个简单的示例显示。不,除非您处理好它,否则该对象将泄漏。最好的方法是为成员变量使用智能指针。一般规则是,在堆栈展开期间,完全构造的对象将被销毁,这同样适用于m_member_str变量,但由于它是原始指针,因此析构函数将非常简单,不会触及指向的对象。此示例是智能指针的经典用例Bat未完全构造,因此不会调用析构函数,但将调用m_member_

如果我这样做

新的
是否被合理分配
std::string
释放?我想可能是因为没有调用析构函数


我使用的不是std::string,而是我自己的类,只是将其作为一个简单的示例显示。

不,除非您处理好它,否则该对象将泄漏。最好的方法是为成员变量使用智能指针。一般规则是,在堆栈展开期间,完全构造的对象将被销毁,这同样适用于
m_member_str
变量,但由于它是原始指针,因此析构函数将非常简单,不会触及指向的对象。

此示例是智能指针的经典用例
Bat
未完全构造,因此不会调用析构函数,但将调用
m_member_str
和所有其他完全构造的成员的析构函数。如果您不想要像
try{foo();}catch(…){delete m_member_str;}
这样丑陋的块,那么您必须熟悉RAII


std::auto_ptr
boost::scoped_ptr
将在C++03或C++11中对您有所帮助。将它们用于自有成员指针几乎没有什么缺点。

您完全改变了您的问题-使我原来的答案无效-P

是否为字符串分配了新的释放值

没有

我想这可能只是因为没有调用析构函数

不相关。要获得释放,基本上需要有一个构造的对象,将为其调用析构函数,并且构造函数在其中执行释放(或者可以使用try/catch块并显式执行所有操作)

那么,如果m_member_str是一个成员指针,我如何释放它呢

(首先,最好的通用方法是将成员变量
m_member_str
设置为字符串,而不是字符串指针-然后字符串析构函数将清除。)


如果必须有指针,请使用智能指针捕获指针,以便智能指针的析构函数销毁指向的对象并释放内存。当失败的构造函数在异常处理期间销毁已构造的成员变量时,将调用此函数。

完全构造的对象将调用其析构函数。 部分构造的对象不会

在本例中,您的
Bat
对象是部分构造的,因为您从其构造函数中抛出了一个异常。因此不会调用
~Bat()

然而,
m_member_str
是完全构造的,因此将调用其析构函数。 然而,我们不可能看到该物体的类型

如果它是一个
std::string*
,那么什么也不会发生。它是一个指针,销毁指针不会删除它指向的内存

如果它是某种形式的智能指针,那么将调用它的析构函数,它将安全地处理您分配的内存

一般来说,只要您的成员是RAII对象并且具有有意义的析构函数,那么无论发生什么情况,它们都会被清除


如果没有,就像在本例中,那么你必须自己处理后果,可能是因为你发现了异常,释放内存,然后重试。

顺便说一句,您必须处理此类中的复制构造函数和赋值运算符。@sharptooth此类已从boost::noncopyable继承。为什么您想要
std::string*
成员而不是
std::string
成员?首先,除非有充分的理由,否则不应该从构造函数抛出异常。第二,避免存储原始指针。如果您刚刚分配了内存,请将其放在智能指针中并存储。然后它就会被处理safely@unixman83:“如果无法捕获异常,则无法很好地处理此异常”?同样的答案是:“最好的方法是对成员变量使用智能指针。”…@jalf:除非你有充分的理由,否则你不应该从任何地方抛出异常(或做任何其他事情)-编程是关于编码有理由做的事情。:-)如果建议使用
std::auto_ptr
,那么值得指出的是,它将从默认生成的复制构造函数中删除任何可能的值语义行为,这样该类在STL容器中就不安全了。@TonyDelroy:这一点很好。我想补充一点,这是一个动态分配成员指针的特性,而不是bug:三的规则将在编译时进行检查。@TonyDelroy您所说的令人困惑。托尼所说的是,这门课不应该被模仿。i、 e.从boost继承:不可复制。
Bat::Bat() : m_member_str(new std::string("Am I freed?"))
{
  throw std::runtime_error("oops");
}