繁体   English   中英

C ++返回MyClass * vs MyClass

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM