如何使智能指针指向对象的副本



如何创建一个智能指针,该指针指向原始对象而是在对象的副本上?

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_ptrstd::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();
}

相关内容

  • 没有找到相关文章

最新更新