std::shared_ptr数据的赋值与memcpy

3
我正在使用C++11中的std::shared_ptr,并且想了解是否最好以这种方式分配类型为T的结构体:
T a_data;
std::shared_ptr<T> my_pointer(new T);
*my_pointer = a_data;

或者像这样:

memcpy(&my_pointer, data, sizeof(T));

或者像这样:
my_pointer.reset(a_data);

祝好!

Mike


PS. 我正在翻译使用指针、memcpy/free/malloc 等操作频繁的遗留 C 代码。我希望通过 shared_ptr 来减少这些操作的数量。 - madduci
memcpy 不提供您正在寻找的功能。请避免使用它。而其他两个中只有一个可以编译。 - R. Martinho Fernandes
目前为止,它们三个都编译通过了。但我仍然无法测试它们。 - madduci
1
如果编译成功,T 就具有相当奇特的属性。 - Angew is no longer proud of SO
1个回答

8
他们各自有不同的功能。
T a_data;
std::shared_ptr<T> my_pointer(new T);
*my_pointer = a_data;

这里将会分配一个类型为 T 的新对象(称其为n),由my_pointer管理。然后,对象a_data将被复制分配到n中。

2.

memcpy(&my_pointer, a_data, sizeof(T));  // I assume you meant a_data here, not data

那是完全无意义的-它正在用a_data的内容覆盖shared_ptr本身。这是未定义的行为(预计会崩溃或内存损坏)。 也许你实际上是想使用my_pointer.get()而不是&my_pointer(也就是说,你想把数据复制到所指向的对象中)?如果是这样,只要T是平凡可复制的类型——这意味着它没有非平凡的复制或移动构造函数、没有非平凡的复制或移动赋值运算符,并且有一个平凡的析构函数——它就可以工作。但为什么要依赖这一点,当正常的赋值(*my_pointer=a_data;)对于这种情况完全相同,而且对于非平凡可复制的类也适用呢? 3.
my_pointer.reset(a_data);

通常情况下,这段代码不能直接编译,需要使用my_pointer.reset(&a_data);。这是一场灾难的开始——你将my_pointer指向自动(局部)变量a_data并使它拥有所有权。这意味着当my_pointer超出作用域时(实际上是当最后一个共享所有权的指针超出作用域时),它会调用删除器,通常会调用delete。而这个指针指向的是没有使用new分配的a_data变量。再次欢迎来到未定义行为领域!
如果你只需要使用shared_ptr管理动态分配的a_data副本,则可以按照以下方式操作:
T a_data;
std::shared_ptr<T> my_pointer(new T(a_data));

甚至更好的是:
T a_data;
auto my_pointer = std::make_shared<T>(a_data);

好的,谢谢!对于包含其他结构体 shared_ptr 的类型 T 的结构体仍然有效吗?(是的,我手头这个 C 旧代码真是个噩梦) - madduci
@blackibiza 我的两个解决方案将完美地工作(执行 浅拷贝)。看起来你应该更多地了解在C++中如何复制和赋值;也许可以去找一本好书 - Angew is no longer proud of SO
我知道C++中的赋值是如何工作的。我只是因为智能指针而有疑虑,因为我以前从未使用过它们。 - madduci
1
@blackibiza 嗯,智能指针就像其他类一样,它的复制和赋值操作已经有文档。所以如果你理解了复制和赋值,这些文档应该可以为你解决问题。 - Angew is no longer proud of SO

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接