Ash*_*iya 2 c++ stl shared-ptr stdvector allocator
请参阅以下代码片段。
根据我的理解:
a) 'p1' 和 'p2' 对象在堆栈中创建,并在 getPoints() 方法结束时销毁。
b)当使用 push_back( )将p1和p2添加到向量时,默认分配器会创建 Point 的新实例并将p1和p2的值 (x,y) 复制到这些新创建的实例中。
我的问题是:
1)我的理解正确吗?
如果是这样的话 ;
2) 如果分配器创建了新的 Point 对象,为什么我只看到两行“Points created”?
因为我希望看到p1和p2 的两行以及分配器新创建的对象的两行。
3)分配器如何为新创建的对象的 x,y 字段分配原始值?它是否使用原始内存复制?
4) 共享指针是从方法返回向量的推荐方式吗?
#include <iostream>
#include <vector>
using namespace std;
struct Point {
Point() {
std::cout<< "Point created\n";
x=0;
y=0;
}
int x;
int y;
};
std::shared_ptr< vector<Point> > getPoints() {
std::shared_ptr< vector<Point> > ret = std::make_shared< vector<Point> >();
Point p1;
p1.x=100;
p1.y=200;
Point p2;
p2.x = 1000;
p2.y = 2000;
ret->push_back(p1);
ret->push_back(p2);
return ret;
}
int main(int argc, char** argv)
{
std::shared_ptr< vector<Point> > points = getPoints();
for(auto point : *(points.get())) {
std::cout << "Point x "<<point.x << " "<< point.y<<"\n";
}
}
Run Code Online (Sandbox Code Playgroud)
问:我的理解正确吗?
答:你的理解是部分正确的。
问:如果分配器创建了新的 Point 对象,为什么我只看到两行“Points created”?
答:分配器不会创建新对象 - 分配器仅在需要时分配更多内存。您在向量中插入的对象是复制构造的。因为您还没有创建复制构造函数,所以编译器为您生成了一个。
问:分配器如何为新创建的对象的 x,y 字段分配原始值?它是否使用原始内存复制?
A:如上一题所述,分配器只分配内存,不创建或销毁对象。复制字段的行为由复制构造函数完成,该构造函数在您执行push_back. 自动生成的复制构造函数将对每个类的成员进行成员方式的复制构造。在您的情况下,x并且y是原始类型,因此它们只是原始内存复制。如果成员是复杂对象,则将调用它们的复制构造函数。
问:共享指针是从方法返回向量的推荐方式吗?
答:这取决于您的用例,并且是基于意见的。我个人的建议,这适用于所有类型的对象是:
std::vector<Point> getPoints())std::unique_ptr。这几乎适用于您可能想要创建的所有工厂函数。即使您以后想要共享所有权(参见第 3 点),您也可以通过从 unique_ptr( std::shared_ptr<T> shared = std::move(unique))移动来构造 shared_ptr ;shared_ptr除非您确实需要共享ptr 的所有权,否则请避免使用。shared_ptr推理起来更复杂,可以创建难以调试的循环,导致内存泄漏,并且在性能方面更重(因为与它们的引用计数和控制块的额外分配内存相关的原子操作)。如果您认为需要 a shared_ptr,请重新考虑您的设计并考虑是否可以使用 a unique_ptr。在内部,std::vector 正在使用堆上使用默认分配器(或提供的自定义用户,如果您提供)分配的内存。这种分配发生在幕后,与向量的大小和向量中的元素数量无关(但总是 >= size())。您可以使用该capacity()函数获取向量为多少元素分配了存储空间。当你打电话时push_back(),会发生什么:
capacity())来容纳另外一个元素,则传递给 push_back 的参数是复制构造的,如果使用push_back( const T& value )变体则使用复制构造函数,或者如果使用则使用push_back( T&& value )移动构造函数移出。reserve()在插入元素之前使用,以确保您的向量将有足够的容量来容纳至少尽可能多的元素而无需新分配。分配新内存后,向量通过复制或移动它们(如果它们不可复制插入)将所有现有元素重新分配到新存储中。此重新分配将使所有迭代器和对向量中元素的引用无效(警告:当重新分配有点复杂时,将使用精确复制与移动的规则,但这是一般情况)