如何检测模板是否为指针类型



我的代码中有几个问题。第一个是在变量"Element"中,它对我来说很好,只要发送模板的类的构造函数的变量有默认值,有没有办法跳过构造函数而不在类中放入默认值?另一个问题是,当谈到释放内存时,当T是指针类型时,我需要进行删除,但就在我放入代码时,我遇到了一个错误,有其他解决方案可以帮助我吗?我会注意你的答案,谢谢:D

namespace Linked{
template <class T>
struct Nodo{
const bool isponter = is_pointer<T>::value;
T Element;
Nodo<T> *Next;
Nodo(){
this->Next = nullptr;
}
~Nodo(){
if(is_pointer<T>::value)
delete Element;
}
};

}

namespace Linked{
template <class T>
struct Nodo{
T Element;
Nodo<T> *Next = nullptr;
~Nodo(){
if constexpr (std::is_pointer<T>::value)
delete Element;
}
};

您还应该考虑T是否是指向数组的指针。

您的代码唯一的语法问题是,您没有#include <type_traits>,忘记了is_pointer<T>::value之前的std::

但你试图做的事情会带来所有权方面的问题。当Nodo包含一个指针时,它不应该拥有该指针所指向的对象。所以你不能只delete那个指针,因为你甚至不知道它指向哪里。考虑以下三种情况,每种情况都需要不同的处理,但你无法确定你面临的是什么情况:

Nodo<int*> n1, n2, n3;
n1.Element = new int(1); // requires delete
n2.Element = new int[10]; // requires delete[], crashes with delete
int i = 0;
n3.Element = &i; // no delete at all, crashes with delete

通常,无论谁在堆上分配了一个对象,都要负责释放它。Nodo不应该试图释放它没有分配的内存。

由于您没有指定c++版本,我假设您使用最新的版本,现在是c++17。最适合您现有代码的是使用if constexpr,我不会详细说明,因为还有其他很好的答案。如果您被困在C++14或C++11上(或者更糟的是,03/98,在这种情况下您应该简单地升级(,您将需要专门化您的模板。(我会回到这里(

然而,这段代码违反了CppCoreGuidelines:ES.24: Use a unique_ptr<T> to hold pointers。通过编写模板来检测原始指针并删除它,总是必须进行分配。因此,您的链接列表不能引用现有内容的某些子数据。正如评论中所回避的那样,如果用户希望清理内存,请使用std::unique_ptr。一个例子:

namespace Linked{
template <class T>
struct Nodo{
T Element;
Nodo<T> *Next{nullptr};
Nodo() = default;
~Nodo() = default;
};
}
// Has ownership
auto node = Nodo<std::unique_ptr<int>>{};
node.element = std::make_unique<int>(42);
// Has ownership (to array of 42 elements)
auto node = Nodo<std::unique_ptr<int[]>>{};
node.element = std::make_unique<int[]>(42);
// No ownership
int value = 42;
auto node = Nodo<int>{};
node.element = &value;

有了这一点,所有权对来电者来说是明确的,对你来说是透明的。(因为您不需要了解数组,std::unique_ptr知道这一点(您可能需要对t进行一些限制,比如添加static_assert(std::is_nothrow_move_constructable<T>);

上述解决方案解决了C++11及以上版本中的问题,应该是推荐的方法。

如果没有,如果您的条件在C++17中的专用类中不可捕获,请使用if constexpr。以及C++14和C++11中的部分专业化。

namespace Linked{
template <class T>
struct Nodo{
T Element;
Nodo<T> *Next{nullptr};
Nodo() = default;
~Nodo() = default;
};
template <class T>
struct Nodo<T*>{
T *Element{nullptr};
Nodo<T> *Next{nullptr};
Nodo() = default;
~Nodo() { delete Element; }
};
}

如果你不想重复你的代码太多

namespace Linked{
template <class T, class Me>
struct AbstractNodo{
T Element;
Me *Next{nullptr};
// All common code
};
template <class T>
struct Nodo : AbstractNodo<T, Nodo<T>>{
Nodo() = default;
~Nodo() = default;
};
template <class T>
struct Nodo<T*> : AbstractNodo<T, Nodo<T*>>{
Nodo() = default;
~Nodo() { delete Element; }
};
}

还有一种方法可以专门化单个方法,但是,我不太熟悉它,请参阅Stack overflow:模板化类中单个方法的模板专门化以了解更多详细信息。

相关内容

  • 没有找到相关文章

最新更新