Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/131.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
为任意数据分配和解除分配使用“新字符”大小的C++安全性_C++_Dynamic Memory Allocation - Fatal编程技术网

为任意数据分配和解除分配使用“新字符”大小的C++安全性

为任意数据分配和解除分配使用“新字符”大小的C++安全性,c++,dynamic-memory-allocation,C++,Dynamic Memory Allocation,我有以下职能: private: static char* new_data(std::size_t size) { return new char[size]; } template<typename T> static char* new_data(T& value) { return reinterpret_cast<char*>(new (new_data(sizeof(T))) T(value)); } template<t

我有以下职能:

private:
    static char* new_data(std::size_t size) { return new char[size]; }
    template<typename T> static char* new_data(T& value) { return reinterpret_cast<char*>(new (new_data(sizeof(T))) T(value)); }
    template<typename T> static char* new_data(T&& value) { return reinterpret_cast<char*>(new (new_data(sizeof(T))) T(value)); }
    static void delete_data(char* data) { return delete[] data; }

谢谢所有帮助我的人。虽然我的问题从未得到完全回答,但基于我对和的阅读,我非常确信我的代码是安全的,尽管不确定。而且我可能有。。。语法完全错误,但我应该在实际尝试编译和使用它时找出答案。

您基本上是在重新发明:

T* t = new T(value);
T* u = new T(std::move(value));
只是它的功能要小得多,因为除了复制和移动之外,我不能使用任何其他的t构造函数。甚至不默认!还要注意,您的第二个构造函数是不正确的-您应该从值转发,而不是复制它,并且拥有转发引用构造函数会使拥有左值引用构造函数变得多余。此外,您还希望创建一个decation\u t,而不是一个t-因为t可以是引用类型

而且它不太安全,因为。。。那么,最后我该怎么处理t和u呢?您可以调用delete_data。这样可以释放内存,但不会破坏对象。你错过了一个析构函数调用。删除t对您来说都是如此

基本上,与普通的原始new和delete相比,这既没有优势,也有一些重要的劣势。现代C++有比智能指针更具优势的工具。如果有疑问,请使用这些工具

还值得指出的是,这两种重载:

static char* new_data(std::size_t size);
template<typename T> static char* new_data(T&& value);

以一种可能让人非常困惑的方式做完全不同的事情。new_data42分配4个字节,并将新闻42放入其中。新的_数据大小_t42分配42个字节。这很容易出错

你基本上是在重塑:

T* t = new T(value);
T* u = new T(std::move(value));
只是它的功能要小得多,因为除了复制和移动之外,我不能使用任何其他的t构造函数。甚至不默认!还要注意,您的第二个构造函数是不正确的-您应该从值转发,而不是复制它,并且拥有转发引用构造函数会使拥有左值引用构造函数变得多余。此外,您还希望创建一个decation\u t,而不是一个t-因为t可以是引用类型

而且它不太安全,因为。。。那么,最后我该怎么处理t和u呢?您可以调用delete_data。这样可以释放内存,但不会破坏对象。你错过了一个析构函数调用。删除t对您来说都是如此

基本上,与普通的原始new和delete相比,这既没有优势,也有一些重要的劣势。现代C++有比智能指针更具优势的工具。如果有疑问,请使用这些工具

还值得指出的是,这两种重载:

static char* new_data(std::size_t size);
template<typename T> static char* new_data(T&& value);
以一种可能让人非常困惑的方式做完全不同的事情。new_data42分配4个字节,并将新闻42放入其中。新的_数据大小_t42分配42个字节。这很容易出错

您可以分配std::max\u align\t而不是char,以便安全地对齐对象

但是,这并不能解决在这里调用构造函数和析构函数的问题

RAII已经是一个已解决的问题。没有理由以某种奇怪的方式重新发明这个轮子。使用容器和/或std::shared\u ptr,默认情况下,您的代码将是RAII安全的。

您可以分配std::max\u align\u t而不是char,以便安全对齐对象

但是,这并不能解决在这里调用构造函数和析构函数的问题


RAII已经是一个已解决的问题。没有理由以某种奇怪的方式重新发明这个轮子。使用容器和/或std::shared\u ptr,默认情况下,您的代码是RAII安全的。

您这样做是出于学术兴趣吗?否则,你的实际目标是什么?你很可能是在重新发明轮子。@Baum,正如我说的,这是我正在使用的RAII结构的一部分,它基本上是一个指向垃圾收集内存的句柄,而不是指向句柄。因此,一部分是学术兴趣,另一部分是因为我太懒了,无法找到一种完全符合我要求的类型,而且我只使用标准库。我只会使用智能指针。它们比你能想到的任何东西都要好,因为多年来很多人都在研究代码,任何改进都会被引入。它们很容易使用,并且有很好的文档记录。你这样做是出于学术兴趣吗?否则,你的实际目标是什么?你很可能是在重新发明轮子。@Baum,正如我说的,这是我正在使用的RAII结构的一部分,它基本上是一个指向垃圾收集内存的句柄,而不是指向句柄。因此,一部分是学术兴趣,另一部分是因为我太懒了,无法找到一种完全符合我要求的类型,而且我只使用标准库。我只会使用智能指针。它们比你能想到的任何东西都要好,因为多年来很多人都在研究代码,任何改进都会被引入。它们非常容易使用,而且文档也很好。IIRC,C++标准保证了字符[大小]的分配将是支持的。
erly aligned for any Type sizeofType@Sam谢谢,我不想使用它,因为如果sizeofT不是sizeofstd::max\u align\t的倍数,它会浪费空间。请确保std::max\u align\t通常有4或8个字节长,我确信这些字节可以在服务器中的千兆字节中保留。@Sam哦,你的权利,对我来说是8个字节,我认为对于SSE打包结构应该是16/32/64字节长,我认为需要对齐,我也不使用服务器,但是我创建的对象的数量和大小很小,所以它不应该太多。Irc,C++标准保证字符大小。对于任何类型的sizeofType@Sam,分配都会正确对齐谢谢,我不想使用它,因为如果sizeofT不是sizeofstd::max_align_t的倍数,它会浪费空间。如果std::max_align_t的长度通常为4或8字节,我确信这些可以保留,在服务器的千兆字节中。@Sam哦,你的权利,对我来说是8字节,我想它应该是16/32/64字节长的SSE压缩结构,我相信这也需要对齐我没有使用服务器,但我创建的对象的数量和大小很小,所以这不太重要。我为什么要使用'std::move'/'std::forward'?如果“T”是引用类型,又有什么问题?而且,对于我使用的任何类型,销毁都应该是微不足道的,所以我不需要担心它。我没有使用新Tvalue的原因;因为我不想安全地销毁对象,即使我不知道与“new”一起使用的类型,我本可以使用freedata和mallocsizeofT@Isaac像这样绕过语言机制并没有什么特别安全的。你什么也得不到。如果你想使用malloc和free,只需在你想使用它的地方使用它-不要把它藏在什么地方。@Isaac根据你的编辑,看起来你是在试图重新创造共享\u ptr。同时,为新的_数据提供重载,根据参数执行完全不同的操作不是一个好主意。它不应该调用static char*new_datastd::size_t size{return new char[size];}吗?谢谢你,我会仔细研究的,我从来没有真正理解过智能指针,而且我自己做起来似乎更容易…谢谢你,我把代码放在函数中的唯一原因是我可以简洁地问这个问题,而不必显示struct Constant的代码,因此,我将根据我认为应该调用的重载来内联扩展函数。同样关于SyrdHypTR,主要问题是它需要知道它指向的对象的类型,我想指向任意可能没有C++类型的对象,所以我想把它们当作字节数组来对待。为什么我要使用“STD::MOD/STD::前进”?如果“T”是引用类型,又有什么问题?而且,对于我使用的任何类型,销毁都应该是微不足道的,所以我不需要担心它。我没有使用新Tvalue的原因;因为我不想安全地销毁对象,即使我不知道与“new”一起使用的类型,我本可以使用freedata和mallocsizeofT@Isaac像这样绕过语言机制并没有什么特别安全的。你什么也得不到。如果你想使用malloc和free,只需在你想使用它的地方使用它-不要把它藏在什么地方。@Isaac根据你的编辑,看起来你是在试图重新创造共享\u ptr。同时,为新的_数据提供重载,根据参数执行完全不同的操作不是一个好主意。它不应该调用static char*new_datastd::size_t size{return new char[size];}吗?谢谢你,我会仔细研究的,我从来没有真正理解过智能指针,而且我自己做起来似乎更容易…谢谢你,我把代码放在函数中的唯一原因是我可以简洁地问这个问题,而不必显示struct Constant的代码,因此,我将根据我认为应该调用的重载来内联扩展函数。同样关于SyddY-PTR,主要问题是它需要知道它指向的对象的类型,我想指向任意可能不包含C++类型的对象,所以我想把它们当作字节数组。