
[英]c++: MyClass x(1,2,3) vs MyClass x = MyClass(1,2,3)
[英]C++ returning MyClass* vs MyClass
我有一个正在创建的模板类,我需要一个返回该类的对象并对其进行分配的方法。 我有一个接受2个对象,创建一个新对象并返回它的方法,以及赋值运算符的重载以正确复制成员。
我尝试这样做2种方式(两种方法都是静态的)。
方法1:有效,但这不是不好的做法吗?
template <class T>
MyClass<T>* MyClass<T>::MyFunction(const MyClass& a, const MyClass& b)
{
MyClass<T> *newObject= new MyClass<T>(a.member, b.member2);
//...do stuff to the object
return newObject;
}
方法2:不起作用,但这不是更好的思路吗?
template <class T>
MyClass<T> MyClass<T>::MyFunction(const MyClass& a, const MyClass& b)
{
MyClass<T> newObject(a.member, b.member2);
//...do stuff to the object
return newObject;
}
我对方法1的担心是,我正在堆中创建一个新对象,而从未销毁它。 我将其所有成员分配给MyClass的另一个实例,但是如果我第二次执行该操作,第一个实例会怎样? 我在堆栈上创建的第一个“新”对象是否就坐在那里?
我对方法2的问题是,在调用分配操作重载之前,对象超出了范围。 我研究了复制构造函数并移动了构造函数。 不幸的是,在这种情况下,我看不到有人打电话(可能是这里严重缺乏经验)。
为了完成,这是相关代码的其余部分。
template <class T>
void MyClass<T>::operator = (const MyClass& b)
{
if (this == &b) { return; }
DeleteData();
//just calls the same member removal operation as the destructor
//to clear everything out to receive new data
//...simple member copying stuff
}
template<class T>
inline void MyClass<T>::DeleteData()
{
//call delete on members which need to be deleted manually
}
template <class T>
MyClass<T>::~MyClass()
{
DeleteData();
}
template <class T>
MyClass<T>::MyClass(const T member, const T member2)
{
//member initialization operations
}
用法示例:
MyClass<T> myObj1(member1, member 2);
MyClass<T> myObj2(member1, member 2);
MyClass<T> myObj3 = *(MyClass<T>::MyFunction(myObj1, myObj2));
TL; DR问题:
当在函数内部使用new
返回class*
而不是class
时,当创建的对象不再具有任何引用时会销毁该对象吗?
如果没有,返回在方法中创建的对象的最佳实践是什么?
如果是这样,这种方法是不好的做法吗?
我很抱歉,如果以前没有回答过,我对C ++还是很陌生,以至于我以前的研究未能给我令人满意的答案,这很可能是由于我不知道自己不知道的事情。
实施的解决方案: ((我还添加了一个复制构造函数。没有它,该解决方案仍然适用于该问题的范围,但是超出了此问题范围的某些项目已由一个人解决。希望将来有人会发现此信息有用) )
//this is a static function of MyClass
template <class T>
std::unique_ptr<MyClass<T>> MyClass<T>::MyFunction(const MyClass& a, const MyClass& b)
{
std::unique_ptr<MyClass<T>> newObj = std::make_unique<MyClass<T>>(a.member, b.member2);
//...Be the factory...
return newObj ;
}
int main()
{
MyClass<T> myObj1(member1, member 2);
MyClass<T> myObj2(member1, member 2);
MyClass<T> myObj3 = *(MyClass<T>::MyFunction(myObj1, myObj2));
}
当在函数内部使用
new
返回class*
而不是class
时,当创建的对象不再具有任何引用时会销毁该对象吗?
它不是。 传递给new
必须显式deleted
,或传递给承担其所有权的容器(例如unique_ptr
)。
如果是这样,这种方法是不好的做法吗?
它取决于,但是通常是,通常不建议返回和处理原始指针,因为它易于发生内存泄漏。 您上面的代码确实泄漏(如您所述)。
如果没有,返回在方法中创建的对象的最佳实践是什么?
这取决于。 如果您不介意复制,或者您的对象定义了移动语义,则可以像方法2中一样返回一个具体对象,并希望编译器执行返回值优化 。
如果您确实介意复制,请考虑返回某种智能指针 :
template <class T>
std::unique_ptr<MyClass<T>> MyClass<T>::MyFunction(const MyClass& a, const MyClass& b)
{
auto newObject = std::unique_ptr<MyClass<T> {new MyClass<T>(a.member, b.member2)};
//...do stuff to the object
return newObject;
}
这个怎么样:
template <class T>
std::shared_ptr<MyClass<T>> MyClass<T>::MyFunction(const MyClass& a, const MyClass& b)
{
auto newObject = std::make_shared<MyClass<T>>(MyClass<T>(a.member, b.member2));
//...do stuff to the object
return newObject;
}
如果您考虑返回指针,则这是在现代C ++中实现此目标的正确方法。 共享指针将为您清除所有内容,并且您不会传递副本。 假设您不想使用move构造函数。
编辑:
由于人们在评论中批评了shared_ptr
,因为它用火箭筒杀死了苍蝇(我同意),所以我也提供与unique_ptr
相同的东西。 请注意, unique_ptr
是必须移动而不是复制的唯一对象。
template <class T>
std::unique_ptr<MyClass<T>> MyClass<T>::MyFunction(const MyClass& a, const MyClass& b)
{
auto newObject = std::unique_ptr<MyClass<T>>(new MyClass<T>(a.member, b.member2));
//...do stuff to the object
return newObject;
}
PS:请注意,我没有使用make_unique
(与make_shared
相对)。 这是因为make_unique
是C ++ 14,而不是C ++ 11。
在C ++代码中,到处传递指针是很普遍的。 一般而言,最佳做法是让指针的创建者也销毁它。 但是,也可以将指针的所有权传递给其他人,让他们负责维护和销毁指针。
在您的方法似乎仅是工厂方法的情况下,尤其如此。 认为工厂方法与构造函数相同是完全可以的。 负责创建指针并负责销毁指针的人。
如果您不太关心最佳实践,只是希望它具有内存安全性,则可以在#include <memory>
使用std::shared_pointer
。 这些行为有点像垃圾收集器。 您可以像使用普通指针一样精确地使用它们。 但是,一旦对其的最后一个引用超出范围,它就会为您删除基础指针。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.