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

时间:2017-09-22 17:05:24

标签: c++ opencv pointers memory-management smart-pointers

如何创建一个不指向原始对象但指向对象副本的智能指针?

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更新了我的代码,我尝试在else块中分配对象,以便用临时地址摆脱错误:

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)...); }

我不再理解这个问题了。

4 个答案:

答案 0 :(得分:2)

cv::Mat已经是引用计数对象。它基本上就像shared_ptr<> 你真的不需要在外部shared_ptr<>unique_ptr<>或任何其他额外的智能指针包装器中保存它。

按原样使用。
如果您有cv::Mat img1, img2则:

  • img2 = img1;将使两个变量共享相同的图像(更改一个将更改另一个)。
  • img2 = im1.clone();会为img2提供img1
  • 的独立副本

答案 1 :(得分:1)

如果由于某种原因必须使用exec,那么您应该使用课程copy constructor。否则,#include<stdio.h> #include<stdlib.h> #include<sys/wait.h> #include<unistd.h> int main(int argc, char *argv[]) { int args = argc-1; pid_t childpid = fork(); // error if (childpid < 0) { perror("fork() error"); exit(-1); } // parent process if (childpid != 0) { printf("Parent Process started, now waiting for ID: %d\n", childpid); wait(NULL); printf("Parent Process resumeed. Child exit code 0. Now terminating\n"); exit(0); } // child process if (args > 0) { printf("Child process has begun. %d argument/s provided\n", args); int i; for (i = 1; i <= argc; i++) { execlp(argv[i], argv[i], NULL); } execvp(argv[1], argv); } else { printf("No arguments provided, terminating child\n"); } return 0; } 也会起作用。

C ++ 11

unique_ptr

在跟进问题后解决:

您收到错误shared_ptr,因为#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 *

如果你创建了cv :: Mat,那么请确保为它定义一个合适的拷贝构造函数,否则Mat *会抛出你在问题的后面部分中出现的相同错误。

答案 2 :(得分:0)

使用std::shared_ptr

  

shared_ptr类型的对象具有获取所有权的能力   一个指针,并分享所有权:一旦他们取得所有权,   指针的所有者组负责删除它时   最后一个人释放了所有权。

答案 3 :(得分:0)

智能指针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(_img)都是关于建立对象的生命周期。如果对象的生命周期已在其他地方进行管理,您不想更改对象生命周期的管理方式。

在您的情况下,最简单的解决方案可能是使用 dumb 指针,让生命周期问题完全独立。

std::unique_ptr