如何创建一个智能指针,该指针指向原始对象而是在对象的副本上?
std::unique_ptr<cv::Mat> mat_p;
if(isChangePersistent){
// Use a pointer on the original object
mat_p = std::make_unique<cv::Mat>(&_img);
}else{
// Use a pointer on a copy of the original object
mat_p = std::make_unique<cv::Mat>(&(_img.clone()));
}
这个想法是仅使用指针mat_p
在代码中进一步工作。这样,我不必再检查是否必须在原始副本上进行工作,因为指针总是指向正确的对象。
编译此代码抛出错误error: taking address of temporary [-fpermissive]
。只有第二个std::make_unique
才会引发此错误。_img
是定义此方法的类的成员变量。
我理解的是,因为我将智能指针提供了临时对象的地址。正确的方法是什么?用new
创建对象,并将其创建指向智能指针的构造函数?
编辑:
我使用shared_ptr
更新了代码,我尝试在其他块中分配对象,以便使用临时地址的错误来消除错误:
std::shared_ptr<cv::Mat> mat_p;
if (isChangePersistent) {
// Use a pointer on the original object
mat_p = std::make_shared<cv::Mat>(&_img);
} else {
// Use a pointer on a copy of the original object
cv::Mat* img_tmp = new cv::Mat();
*img_tmp = _img.clone();
mat_p = std::make_shared<cv::Mat>(img_tmp);
}
现在我遇到了这个错误,已经是第一个std::make_shared
:
error: no matching function for call to ‘cv::Mat::Mat(cv::Mat*)’
{ ::new((void *)__p) _Up(std::forward<_Args>(__args)...); }
我不再真正了解问题了。
cv::Mat
已经是参考计数对象。从本质上讲,它像shared_ptr<>
。
您永远不需要在外部shared_ptr<>
,unique_ptr<>
或任何其他其他智能指针包装器中握住它。
只能按原样使用它。
如果您有cv::Mat img1, img2
,则:
-
img2 = img1;
将使两个变量共享相同的图像(更改一个将更改另一个图像)。 -
img2 = im1.clone();
将为img2
提供img1
的独立副本。
如果由于某种原因必须使用unique_ptr
,则应使用班级的复制构造函数。否则shared_ptr
也可以工作。
C 11
#include <memory>
#include <iostream>
struct A
{
int n;
A(int n = 1) : n(n) { }
A(const A& a) : n(a.n) { } // copy constructor
};
int main()
{
A *a1 = new A(1);
std::unique_ptr<A> aptr(a1);
std::unique_ptr<A> bptr(new A(*a1)); // Copy the object a1 points to
}
在后续问题之后解决:
您正在获取错误error: no matching function for call to ‘cv::Mat::Mat(cv::Mat*)’
,因为Mat
的构造函数没有Mat *
类型的过载。但是,您的问题更多是您尝试复制对象而不是缺乏接受Mat *
的构造函数。这是您可以解决错误的方法:
std::shared_ptr<cv::Mat> mat_p;
if (isChangePersistent) {
// Use a pointer on the original object
mat_p = std::make_shared<cv::Mat>(&_img);
} else {
// Create a new shared pointer that holds a copy of _img on the heap
mat_p = std::make_shared<cv::Mat>(cv::Mat(_img));
}
如果您创建了CV :: MAT,则请确保您为其定义了合适的复制构造函数,否则cv::Mat(_img)
将在问题的后面部分丢弃相同的错误。
使用std::shared_ptr
:
shared_ptr
类型的对象具有所有权的能力 指针并分享所有权:一旦获得所有权, 指针的一组所有者对其删除负责 他们中的最后一个发布了所有权。
std::unique_ptr
和 std::shared_ptr
的智能指针均涉及建立对象的寿命。您不想更改对象已经在其他地方进行管理的对象的寿命。
在您的情况下,最简单的解决方案可能是使用 dumb 指针,让生命周期的问题完全独立。
std::unique_ptr<cv::Mat> mat_copy; // not initialized unless needed
cv::Mat * mat_p;
if(isChangePersistent){
// Use a pointer on the original object
mat_p = &_img;
}else{
// Use a pointer on a copy of the original object
mat_copy = new cv::Mat(_img.clone());
mat_p = mat_copy.get();
}