C++ 将std::memcpy用于非平凡可复制类型的对象
该标准定义了我们可以通过以下方式使用std::memcpy int: 对于任何普通的可复制类型T,如果两个指向T的指针指向 不同的T对象obj1和obj2,其中obj1和obj2都不是 基类子对象,如果构成obj1的基础字节(1.7)为 复制到obj2中,obj2随后应保持与obj1相同的值 如果我们将该函数应用于非平凡可复制类型的对象,可能会遇到什么潜在问题?以下代码的工作方式与普通可复制类型类似:C++ 将std::memcpy用于非平凡可复制类型的对象,c++,types,C++,Types,该标准定义了我们可以通过以下方式使用std::memcpy int: 对于任何普通的可复制类型T,如果两个指向T的指针指向 不同的T对象obj1和obj2,其中obj1和obj2都不是 基类子对象,如果构成obj1的基础字节(1.7)为 复制到obj2中,obj2随后应保持与obj1相同的值 如果我们将该函数应用于非平凡可复制类型的对象,可能会遇到什么潜在问题?以下代码的工作方式与普通可复制类型类似: #include <iostream> #include <cstring&
#include <iostream>
#include <cstring>
using std::cout;
using std::endl;
struct X
{
int a = 6;
X(){ }
X(const X&)
{
cout << "X()" << endl;
}
};
X a;
X b;
int main()
{
a.a = 10;
std::memcpy(&b, &a, sizeof(X));
cout << b.a << endl; //10
}
#包括
#包括
使用std::cout;
使用std::endl;
结构X
{
INTA=6;
X(){}
X(常数X&)
{
难道你问:
如果我们将该函数应用于非平凡可复制类型的对象,可能会遇到什么潜在问题
下面是一个非常简单的示例,说明了对非平凡可复制类型的对象使用std::memcpy
的问题
#include <cstring>
struct A
{
A(int size) : size_(size), data_(new int[size]) {}
~A() { delete [] data_; }
// The copy constructor and the copy assignment operator need
// to be implemented for the class too. They have been omitted
// to keep the code here minimal.
int size_;
int* data_;
};
int main()
{
A a1(10);
A a2(20);
std::memcpy(&a1, &a2, sizeof(A));
// When we return from the function, the original data_ of a1
// is a memory leak. The data_ of a2 is deleted twice.
return 0;
}
#包括
结构A
{
A(int-size):size(size),data(newint[size]){
~A(){delete[]数据}
//复制构造函数和复制赋值运算符需要
//也要为类实现。它们已被省略
//使这里的代码保持最少。
int-size_389;;
int*数据;
};
int main()
{
A a1(10);
A a2(20);
std::memcpy(&a1,&a2,sizeof(A));
//当我们从函数返回时,a1的原始数据
//是内存泄漏。a2的数据被删除两次。
返回0;
}
考虑以下程序:
#include <memory>
int main() {
std::shared_pointer<int> x(new int);
{
std::shared_pointer<int> y;
memcpy((void*)&y, (void*)&x, sizeof(x));
}
*x = 5;
}
#包括
int main(){
std::共享_指针x(新int);
{
std::共享_指针y;
memcpy((void*)和y,(void*)和x,sizeof(x));
}
*x=5;
}
因为我们使用memcpy
而不是赋值运算符将x
复制到y
,所以引用计数没有得到更新。因此,在该块末尾,调用了y
的析构函数。它发现它的引用计数为1,这意味着它是指向堆al的唯一共享_指针实例定位整数。所以它会删除它
最后一行<代码>主< /代码>很可能是分段错误,因为<代码> x>代码>指向一个已删除的对象。
明显的UB是明显的。例如,考虑<代码> MycPy < /代码>:a <代码> STD::vector < /代码>,例如,是的,它是有效的,因为结构X是简单的可复制的。如果结构的成员包括任何类型的堆例如,内存,那么您就会遇到问题。好吧,在实际的程序中。在您的测试中没有。@Wlerin X是不可复制的。@T.C.Mmm。它有一个不可复制的复制构造函数。从技术上讲,这可能足以使它不可复制,但类的实际内容可以一个成员一个成员地复制,而不会出现问题。C之前++11,b=a的结果也将与memcpy的结果相同。无论如何,这个示例程序都不是一个好的示例。您的实际问题是什么?您想让我们向您解释什么是未定义的行为?还是您只想确认这实际上是未定义的行为?实际上,向运算符dele传递无效指针很高兴我能回答你的问题。@DmitryFucintv,不客气。