Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/ajax/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 创建boost::shared_ptr的深度副本_C++_C++11_Boost_Shared Ptr - Fatal编程技术网

C++ 创建boost::shared_ptr的深度副本

C++ 创建boost::shared_ptr的深度副本,c++,c++11,boost,shared-ptr,C++,C++11,Boost,Shared Ptr,我有两个共享_ptr向量 typedef boost::shared_ptr <A> someptr; std::vector<someptr>src; std::vector<someptr>dest; typedef boost::sharedptrsomeptr; std::vectorsrc; std::vectordest; 如果我使用dest=src复制,两个向量元素共享相同的内存位置,这会增加指针的引用计数。它们都指向公共位置,并且一个向量元

我有两个共享_ptr向量

typedef boost::shared_ptr <A> someptr;
std::vector<someptr>src;
std::vector<someptr>dest;
typedef boost::sharedptrsomeptr;
std::vectorsrc;
std::vectordest;
如果我使用dest=src复制,两个向量元素共享相同的内存位置,这会增加指针的引用计数。它们都指向公共位置,并且一个向量元素的任何更改都会影响另一个。我理解这是一个浅拷贝,这是预期的行为

但是,如果我想为具有不同内存位置的dest向量元素创建一个深度副本,我应该怎么做?如何实现

boost有实现这一点的功能吗?

当然。最简单的:

#include <vector>
#include <memory>

struct T {};

int main() {
    std::vector<T> a{100};
    auto b = a; // deep copy all T
}
印刷品

a: T T U T T T
b: T T U T T T
a: U T T
b: U T T

std::vector
这在概念上是相似的,但需要您做更多的工作:

#include <vector>
#include <memory>
#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>

struct Base {
  virtual ~Base() = default; // runtime polymorphic
  virtual char const* foo() const = 0;
};

struct T : Base {
  virtual char const* foo() const override { return "T"; }
};
struct U : Base {
  virtual char const* foo() const override { return "U"; }
};

static inline Base* new_clone(Base const& obj) {
    if (auto* p = dynamic_cast<T const*>(&obj))
        return new T{*p};
    if (auto* p = dynamic_cast<U const*>(&obj))
        return new U{*p};
    return nullptr;
}

int main() {
    boost::ptr_vector<Base> a;
    std::generate_n(std::back_inserter(a), 5, [] { return new T{}; });
    // polymorphic
    a.insert(a.begin()+2, new U{});

    auto b = a; // deep copy all elements, derived from Base

    // not sharing the instances:
    assert(&a.front() != &b.front());

    std::cout << "\na:";
    for (auto& el : a) std::cout << " " << el.foo(); 

    std::cout << "\nb:";
    for (auto& el : b) std::cout << " " << el.foo(); 
}
#include <algorithm>
#include <vector>
#include <memory>
#include <iostream>
#include <cassert>

struct Base {
  virtual ~Base() = default; // runtime polymorphic
  virtual char const* foo() const = 0;
};

struct T : Base {
  virtual char const* foo() const override { return "T"; }
};
struct U : Base {
  virtual char const* foo() const override { return "U"; }
};

struct Cloner {
    using Ptr = std::unique_ptr<Base>;
    Ptr operator()(Ptr const& pb) const {
        if (auto* p = dynamic_cast<T const*>(pb.get()))
            return std::make_unique<T>(*p);
        if (auto* p = dynamic_cast<U const*>(pb.get()))
            return std::make_unique<U>(*p);
        return nullptr;
    }
};

int main() {
    std::vector<std::unique_ptr<Base> > a;
    a.push_back(std::make_unique<T>());
    a.push_back(std::make_unique<U>());
    a.push_back(std::make_unique<T>());

    std::vector<std::unique_ptr<Base> > b;

    // deep copy all elements, derived from Base
    Cloner clone;
    std::transform(begin(a), end(a), back_inserter(b), clone);

    // not sharing the instances:
    assert(&*a.front() != &*b.front());

    std::cout << "\na:";
    for (auto& p : a) std::cout << " " << p->foo(); 

    std::cout << "\nb:";
    for (auto& p : b) std::cout << " " << p->foo(); 
}
  // deep copy all elements, derived from Base
  auto b = boost::copy_range<upvec>(a | transformed(Cloner{}));
  // deep copy all elements, derived from Base
  auto b = ranges::to_vector(a | ranges::views::transform(Cloner{}));
#include <boost/poly_collection/base_collection.hpp>
#include <memory>
#include <iostream>
#include <cassert>

struct Base {
  virtual ~Base() = default; // runtime polymorphic
  virtual char const* foo() const = 0;
};

struct T : Base {
  virtual char const* foo() const override { return "T"; }
};
struct U : Base {
  virtual char const* foo() const override { return "U"; }
};

int main() {
    using C = boost::poly_collection::base_collection<Base>;
    
    C a;
    a.insert(T{});
    a.insert(U{});
    a.insert(T{});

    // deep copy all elements, derived from Base
    auto b = a;

    // not sharing the instances:
    assert(&*a.begin() != &*b.begin());

    std::cout << "\na:";
    for (auto& p : a) std::cout << " " << p.foo(); 

    std::cout << "\nb:";
    for (auto& p : b) std::cout << " " << p.foo(); 
}
vector
但“更简单”? 如果您愿意,您可以使用一些“魔法”来简化:

  • 使用增压范围

    #include <vector>
    #include <memory>
    #include <boost/ptr_container/ptr_vector.hpp>
    #include <iostream>
    
    struct Base {
      virtual ~Base() = default; // runtime polymorphic
      virtual char const* foo() const = 0;
    };
    
    struct T : Base {
      virtual char const* foo() const override { return "T"; }
    };
    struct U : Base {
      virtual char const* foo() const override { return "U"; }
    };
    
    static inline Base* new_clone(Base const& obj) {
        if (auto* p = dynamic_cast<T const*>(&obj))
            return new T{*p};
        if (auto* p = dynamic_cast<U const*>(&obj))
            return new U{*p};
        return nullptr;
    }
    
    int main() {
        boost::ptr_vector<Base> a;
        std::generate_n(std::back_inserter(a), 5, [] { return new T{}; });
        // polymorphic
        a.insert(a.begin()+2, new U{});
    
        auto b = a; // deep copy all elements, derived from Base
    
        // not sharing the instances:
        assert(&a.front() != &b.front());
    
        std::cout << "\na:";
        for (auto& el : a) std::cout << " " << el.foo(); 
    
        std::cout << "\nb:";
        for (auto& el : b) std::cout << " " << el.foo(); 
    }
    
    #include <algorithm>
    #include <vector>
    #include <memory>
    #include <iostream>
    #include <cassert>
    
    struct Base {
      virtual ~Base() = default; // runtime polymorphic
      virtual char const* foo() const = 0;
    };
    
    struct T : Base {
      virtual char const* foo() const override { return "T"; }
    };
    struct U : Base {
      virtual char const* foo() const override { return "U"; }
    };
    
    struct Cloner {
        using Ptr = std::unique_ptr<Base>;
        Ptr operator()(Ptr const& pb) const {
            if (auto* p = dynamic_cast<T const*>(pb.get()))
                return std::make_unique<T>(*p);
            if (auto* p = dynamic_cast<U const*>(pb.get()))
                return std::make_unique<U>(*p);
            return nullptr;
        }
    };
    
    int main() {
        std::vector<std::unique_ptr<Base> > a;
        a.push_back(std::make_unique<T>());
        a.push_back(std::make_unique<U>());
        a.push_back(std::make_unique<T>());
    
        std::vector<std::unique_ptr<Base> > b;
    
        // deep copy all elements, derived from Base
        Cloner clone;
        std::transform(begin(a), end(a), back_inserter(b), clone);
    
        // not sharing the instances:
        assert(&*a.front() != &*b.front());
    
        std::cout << "\na:";
        for (auto& p : a) std::cout << " " << p->foo(); 
    
        std::cout << "\nb:";
        for (auto& p : b) std::cout << " " << p->foo(); 
    }
    
      // deep copy all elements, derived from Base
      auto b = boost::copy_range<upvec>(a | transformed(Cloner{}));
    
      // deep copy all elements, derived from Base
      auto b = ranges::to_vector(a | ranges::views::transform(Cloner{}));
    
    #include <boost/poly_collection/base_collection.hpp>
    #include <memory>
    #include <iostream>
    #include <cassert>
    
    struct Base {
      virtual ~Base() = default; // runtime polymorphic
      virtual char const* foo() const = 0;
    };
    
    struct T : Base {
      virtual char const* foo() const override { return "T"; }
    };
    struct U : Base {
      virtual char const* foo() const override { return "U"; }
    };
    
    int main() {
        using C = boost::poly_collection::base_collection<Base>;
        
        C a;
        a.insert(T{});
        a.insert(U{});
        a.insert(T{});
    
        // deep copy all elements, derived from Base
        auto b = a;
    
        // not sharing the instances:
        assert(&*a.begin() != &*b.begin());
    
        std::cout << "\na:";
        for (auto& p : a) std::cout << " " << p.foo(); 
    
        std::cout << "\nb:";
        for (auto& p : b) std::cout << " " << p.foo(); 
    }
    

全自动: 这不会保留顺序,但它的优点是您不必提出克隆逻辑,您可以按类型等进行智能迭代:

#include <vector>
#include <memory>
#include <boost/ptr_container/ptr_vector.hpp>
#include <iostream>

struct Base {
  virtual ~Base() = default; // runtime polymorphic
  virtual char const* foo() const = 0;
};

struct T : Base {
  virtual char const* foo() const override { return "T"; }
};
struct U : Base {
  virtual char const* foo() const override { return "U"; }
};

static inline Base* new_clone(Base const& obj) {
    if (auto* p = dynamic_cast<T const*>(&obj))
        return new T{*p};
    if (auto* p = dynamic_cast<U const*>(&obj))
        return new U{*p};
    return nullptr;
}

int main() {
    boost::ptr_vector<Base> a;
    std::generate_n(std::back_inserter(a), 5, [] { return new T{}; });
    // polymorphic
    a.insert(a.begin()+2, new U{});

    auto b = a; // deep copy all elements, derived from Base

    // not sharing the instances:
    assert(&a.front() != &b.front());

    std::cout << "\na:";
    for (auto& el : a) std::cout << " " << el.foo(); 

    std::cout << "\nb:";
    for (auto& el : b) std::cout << " " << el.foo(); 
}
#include <algorithm>
#include <vector>
#include <memory>
#include <iostream>
#include <cassert>

struct Base {
  virtual ~Base() = default; // runtime polymorphic
  virtual char const* foo() const = 0;
};

struct T : Base {
  virtual char const* foo() const override { return "T"; }
};
struct U : Base {
  virtual char const* foo() const override { return "U"; }
};

struct Cloner {
    using Ptr = std::unique_ptr<Base>;
    Ptr operator()(Ptr const& pb) const {
        if (auto* p = dynamic_cast<T const*>(pb.get()))
            return std::make_unique<T>(*p);
        if (auto* p = dynamic_cast<U const*>(pb.get()))
            return std::make_unique<U>(*p);
        return nullptr;
    }
};

int main() {
    std::vector<std::unique_ptr<Base> > a;
    a.push_back(std::make_unique<T>());
    a.push_back(std::make_unique<U>());
    a.push_back(std::make_unique<T>());

    std::vector<std::unique_ptr<Base> > b;

    // deep copy all elements, derived from Base
    Cloner clone;
    std::transform(begin(a), end(a), back_inserter(b), clone);

    // not sharing the instances:
    assert(&*a.front() != &*b.front());

    std::cout << "\na:";
    for (auto& p : a) std::cout << " " << p->foo(); 

    std::cout << "\nb:";
    for (auto& p : b) std::cout << " " << p->foo(); 
}
  // deep copy all elements, derived from Base
  auto b = boost::copy_range<upvec>(a | transformed(Cloner{}));
  // deep copy all elements, derived from Base
  auto b = ranges::to_vector(a | ranges::views::transform(Cloner{}));
#include <boost/poly_collection/base_collection.hpp>
#include <memory>
#include <iostream>
#include <cassert>

struct Base {
  virtual ~Base() = default; // runtime polymorphic
  virtual char const* foo() const = 0;
};

struct T : Base {
  virtual char const* foo() const override { return "T"; }
};
struct U : Base {
  virtual char const* foo() const override { return "U"; }
};

int main() {
    using C = boost::poly_collection::base_collection<Base>;
    
    C a;
    a.insert(T{});
    a.insert(U{});
    a.insert(T{});

    // deep copy all elements, derived from Base
    auto b = a;

    // not sharing the instances:
    assert(&*a.begin() != &*b.begin());

    std::cout << "\na:";
    for (auto& p : a) std::cout << " " << p.foo(); 

    std::cout << "\nb:";
    for (auto& p : b) std::cout << " " << p.foo(); 
}

你的向量是否只包含
A
的实例,或者也包含从其派生的类的实例?例如:src包含2个元素。dest是一个新的空向量,需要深度副本。它们没有派生类。
For(auto const&p:src)dest.push_back(make_shared(*p))
Eljay的解决方案只有在向量不能包含从A派生的类的情况下才有效。如果可以,您将需要其他内容。使用上面的代码语句会抛出错误:showing cannot convert boost::shared_ptr to(const A&)。充实了三个选项:。只有后者能完全为您完成克隆。非常感谢您共享代码。事实上,我拥有的两个向量对象属于同一个类,其中一个不是从另一个类派生的。每当您以b=a进行复制时,它都会导致浅复制。我需要从a到b的深度复制或按值复制。使用复制构造函数从a(b(*a))复制b,是否抛出错误。您是否可以显示问题(可能通过编辑实时样本?)。我不明白你的意思。在我所有的方法中,复制的向量都是相同的类型,它们的副本都很深,并且它们都编译没有错误。