使用此指针的memcpy安全吗? 我现在正在用C++编写一个自己的字符串实现。(只是为了锻炼)
但是,我目前拥有此副本构造函数:使用此指针的memcpy安全吗? 我现在正在用C++编写一个自己的字符串实现。(只是为了锻炼),c++,arrays,memcpy,this-pointer,C++,Arrays,Memcpy,This Pointer,但是,我目前拥有此副本构造函数: // "obj" has the same type of *this, it's just another string object string_base<T>(const string_base<T> &obj) : len(obj.length()), cap(obj.capacity()) { raw_data = new T[cap]; for (unsigned i = 0; i &
// "obj" has the same type of *this, it's just another string object
string_base<T>(const string_base<T> &obj)
: len(obj.length()), cap(obj.capacity()) {
raw_data = new T[cap];
for (unsigned i = 0; i < cap; i++)
raw_data[i] = obj.data()[i];
raw_data[len] = 0x00;
}
像那样覆盖*此
的数据安全吗?或者这会产生什么问题
提前谢谢 它将产生问题。所有引用和指针都将被复制,甚至是指向原始数据的指针,这些数据将与源对象相同 作为使用memcpy的必要条件,您的班级应该:
- 是
- 没有引用或指针,除非:静态指针或不拥有指向的数据。除非您知道自己在做什么,比如实现写时拷贝机制,或者这种行为是在其他情况下有意和管理的
不,这不安全。从cppreference.com: 如果对象不可
普通可复制
,则不会指定memcpy
的行为,并且可能未定义
您的类不是可复制的,因为它的复制构造函数是用户提供的
此外,您的复制构造函数将只进行浅层复制(如果您愿意,这可能很好,例如,字符串应用的写时复制机制)。从有限的片段中可以明显看出,
原始数据是一个成员,并且是指向新[]
的ed数组T
的指针。如果memcpy对象,则memcpy此指针。不复制数组
看看你的析构函数。它可能会无条件地调用delete[]
。它不知道有多少份。这意味着它调用delete[]
的频率太高。这是可以解决的:您需要类似于shared\u ptr
的东西。这一点都不微不足道;您必须担心共享计数的线程安全性。显然,您不能只memcpy
对象,因为这不会更新共享计数 正如其他人所说,为了使memcpy
正常工作,被复制的对象必须是可复制的。对于模板中的任意类型,如T
,您无法确定这一点。当然,你可以检查一下,但是让别人检查要容易得多。使用std::copy\n
,而不是编写循环并对其进行调整。如果合适,它将使用memcpy
,如果不合适,它将使用逐元素复制。所以改变
raw_data = new T[cap];
for (unsigned i = 0; i < cap; i++)
raw_data[i] = obj.data()[i];
这还有一个小小的优点,就是不必在每次循环中都计算obj.data()
,这是一种编译器可能会也可能不会应用的优化;几乎是重复的:您还可以使用strcpy,它在空字符处停止。与MimcPype相比,它的性能可能有所不同。要考虑的另一件事是,现代编译器往往足够聪明,能够识别第一个示例中的循环,并在适当的时候用MeMCPY替换它。所以这可能是一个过早的优化。顺便说一句,你只需要复制len
对象,而不是cap
。“平凡可复制”是什么意思?我不确定简单可复制就足够了,尽管这是必要的。@codekaizer一点也不:std::cout@DanielLangr,是的,刚刚读过。基于注释-std::string在c++14和onwards@codekaizer不,请阅读下一条评论:“包含std::string
的对象从来都不是可复制的对象”。如果指针不拥有所指向的数据,那么指针就可以了。否则,我们会多次删除同一个内存。。。@Aconcagua说了些什么。已编辑。当然,它们也可以被引用。至于写时复制机制。这就是为什么我会小心如此强烈的声明。好吧,我又编辑了一次,但这应该是它。关于引用和指针的警告是强制性的。如果您有引用成员,并且执行memcpy
,则表示您正在重新绑定引用。这是违法的。
raw_data = new T[cap];
for (unsigned i = 0; i < cap; i++)
raw_data[i] = obj.data()[i];
raw_data = new T[cap];
std::copy_n(obj.data(), cap, raw_data);