繁体   English   中英

在 C++ 中,如何正确获取指向向量的共享指针,最大限度地减少复制构造函数调用的次数?

[英]In C++, how to correctly obtain a shared pointer to a vector , minimizing the number of copy constructor calling?

我需要一个将 shared_ptr 返回到包含大量对象的向量的函数。 下面的代码实现了这一点,但可以看到复制构造函数被调用了多次。

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

using namespace std;

class A {
public:
    int IA ;

    A(int ia) {
        cout << "Constructor is called\n" ;
        IA = ia ;
    }

    A(const A& a) {
        cout << "Copy constructor is called\n" ;
        IA = a.IA ;
    }
} ;


shared_ptr<vector<A>> foo() {

    vector<A> myA ; 

    myA.push_back(A(10)) ;
    myA.push_back(A(20)) ;
    
    return make_shared<vector<A>>(myA) ; 
}



int main() {

    shared_ptr<vector<A>> myA ;
    myA = foo() ;
    
    return 0 ;
}

在实际情况下,A 也可能更大,所以要make_shared<vector<A>>(myA) ; 会导致不必要的复制过程。 我想知道是否有任何方法可以减少复制构造函数的调用时间。

这条线

return make_shared<vector<A>>(myA) ; 

正在制作不必要的副本。 您无需先创建向量,然后将其复制到另一个动态分配的向量。 您只需要创建一个向量:

shared_ptr<vector<A>> foo() {
    return make_shared<vector<A>>(std::initializer_list<A>{{10},{20}}); 
}

谢谢! 现在的代码是:

shared_ptr<vector<A>> foo2() {
    auto ptr = make_shared<vector<A>>()  ;
    (*ptr).reserve(99) ;
    ptr->emplace_back(A(10)) ;
    ptr->emplace_back(A(20)) ;

    return ptr ;
}

int main() {
    shared_ptr<vector<A>> myA, myA2 ;
    myA2 = foo2() ;
    cout << (*myA2)[0].IA << endl;
    return 0 ;
}

复制构造函数调用的数量减少到两个。 是否可以继续避免调用复制构造函数,因为我认为没有理由在构造后进行复制。

您的代码中有两种用法会导致额外的复制。

  1. myA.push_back(A(10))将创建一个类A的临时对象,然后将其复制到向量myA中。 请注意,我们无法通过更改为myA.emplace_back(A(10))来减少此类重复。 它还将创建一个临时A对象,然后以临时 (xvalue) 作为参数调用A的构造函数。 这将调用复制构造函数(因为您没有提供移动构造函数)。

  2. make_shared<vector<A>>(myA)将在std::shared_ptrmyA创建托管对象,该对象将被复制。 复制向量将复制其所有元素。

解决方案:

  1. emplace_back提供适当的参数。 在这里我们可以写myA.emplace_back(10) 现在它将使用参数10调用A的构造函数,这将选择构造函数A(int) 即直接在vector中构造A类的对象,而不是先创建一个临时的,然后再复制到vector中。

  2. 通过make_shared<vector<A>>(std::move(myA))myA移动到shared_ptr中。 这里它不会复制向量中的元素。

请注意,随着向量容量的增加,它的元素也将被复制。 有一些解决方案。 如果您知道元素的数量,则可以使用reserve()来预先分配足够的内存。 您还可以为类A提供一个 noexcept 移动构造函数,以避免在更改容量时复制。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM