为什么从引用中创建共享指针会复制对象?

2022-05-12 00:00:00 复制 pass-by-reference c++ shared-ptr

我打算让一个构造函数接受引用,然后创建指向作为引用传递的对象的指针,并将这些指针存储在一个字段中。然而,由于某种原因,我这样做的方式,正在创建副本,我不知道为什么:

#include <iostream>
#include <vector>
#include <memory>

// the class with the field of pointers
template<class T, class... Types>
class C
{

private:
    std::vector<std::shared_ptr<T>> mem; // the field of pointers

public:
    C(T& t, Types&... args)
      // make pointers to the objects passed by reference and store them in mem
      : mem{ std::make_shared<T>(t), std::make_shared<T>(args)... }
    {

        // to demonstrate that the pointers point to copies, alter one of the objects (subscript operator expected)
        (*mem[0])[0] = 10;


        // demonstrate the effect on the local copies
        std::cout << "vectors in mem:" << "
";
        for (const auto& x : mem) {
            for (const auto& y : *x) {
                std::cout << y << ' ';
            }
            std::cout << "
";
        }
    }
};

int main()
{
    std::vector<int> v1{ 1, 2, 3 };
    std::vector<int> v2{ 1, 2, 3 };
    std::vector<int> v3{ 1, 2, 3 };

    // make an object of type C with some vectors to store pointers to in field mem
    C<std::vector<int>, std::vector<int>, std::vector<int>> c(v1, v2, v3);

    // demonstrate that original vectors are unaltered
    std::cout << "original vectors:"<< "
";

    for (const auto& y : v1) {
        std::cout << y << ' ';
    }
    std::cout << "
";

    for (const auto& y : v2) {
        std::cout << y << ' ';
    }
    std::cout << "
";

    for (const auto& y : v3) {
        std::cout << y << ' ';
    }
    std::cout << "
";
}

我在这里错过了什么?复制发生在哪里?为什么?


解决方案

原因是std::make_shared<T>(t)make_shared将调用T的构造函数,该构造函数接受给定的参数。并通过引用为其赋予TlValue。

自然会调用复制构造函数。这是一件好事。如果您创建了指向传递给您的对象的共享指针,您的代码可能会是一堆未定义的行为。

我建议您改为通过智能指针接受该参数。它使您的类的用户可以从API本身清楚地了解所有权语义。

相关文章