C++ 什么';这两门课的区别是什么?
下面,我没有将C++ 什么';这两门课的区别是什么?,c++,memory,C++,Memory,下面,我没有将my_ints声明为指针。我不知道内存将分配到哪里。请在这里教育我 #include <iostream> #include <vector> class FieldStorage { private: std::vector<int> my_ints; public: FieldStorage() { my_ints.push_back(1); my_ints.push_back(2)
my_ints
声明为指针。我不知道内存将分配到哪里。请在这里教育我
#include <iostream>
#include <vector>
class FieldStorage
{
private:
std::vector<int> my_ints;
public:
FieldStorage()
{
my_ints.push_back(1);
my_ints.push_back(2);
}
void displayAll()
{
for (int i = 0; i < my_ints.size(); i++)
{
std::cout << my_ints[i] << std::endl;
}
}
};
main()
要测试的函数:
int main()
{
FieldStorage obj;
obj.displayAll();
return 0;
}
两者产生相同的结果。区别是什么?在FieldStorage析构函数的第二种情况下,您必须释放分配给vector的内存(以防止内存泄漏)
FieldStorage::~FieldStorage()
{
delete my_ints;
}
第一种方法是首选方法,您不需要向量上的指针,而且忘记了删除它。在第一个示例中,对象是在堆栈上分配的
在第二个示例中,对象在堆中分配,指向该内存的指针存储在堆栈上。正如Mykola Golubyev指出的,在第二种情况下,需要删除向量 第一种方法可能会生成更快的代码,因为优化者知道包括向量在内的整个FieldStorage大小,并且可以在一次分配中为这两种方法分配足够的内存
第二个实现需要两个单独的分配来构造对象。区别在于第二个实现动态分配向量。这里几乎没有什么区别:
- 必须释放向量对象占用的内存(向量对象本身,而不是保存在向量中的对象,因为它由向量正确处理)。您应该使用一些智能指针来保持向量或make(例如在析构函数中): 删除我的链接
- 第一个可能更有效,因为对象是在堆栈上分配的
- 对vector方法的访问具有不同的语法:)
第一个在堆栈上分配,而第二个在堆上分配。FieldStorage的第一个版本包含一个向量。FieldStorage类的大小包含足够容纳向量的字节。当您构造FieldStorage时,向量是在执行FieldStorage的构造函数体之前构造的。当FieldStorage被破坏时,向量也会被破坏 这不一定在堆栈上分配向量;如果堆分配FieldStorage对象,则向量的空间来自该堆分配,而不是堆栈。如果定义全局FieldStorage对象,则向量的空间既不来自堆栈也不来自堆,而是来自为全局对象指定的空间(例如,某些平台上的
.data
或.bss
部分)
请注意,向量执行堆分配以保存实际数据,因此它可能只包含几个指针,或一个指针和两个长度,但它可能包含编译器的STL实现需要的任何内容
FieldStorage的第二个版本包含指向向量的指针。FieldStorage类的大小包括指向向量而不是实际向量的指针的空间。您正在使用FieldStorage构造函数主体中的new为向量分配存储,并且在FieldStorage被销毁时泄漏该存储,因为您没有定义删除向量的析构函数。对象的大小将不同。在第二种情况下,向量*只占用指针的大小(32位机器上为4字节)。在第一种情况下,对象将更大。就内存管理而言,这两个类实际上是相同的。其他几个响应者指出,这两者之间存在差异,一个是在堆栈上分配存储,另一个是在堆上分配存储,但这不一定是真的,即使是在这种情况下,也会产生严重的误导。实际上,不同之处在于
向量的元数据是在哪里分配的;向量
中的实际底层存储是从堆中分配的
看到这一点有点棘手,因为您使用的是std::vector
,所以具体的实现细节是隐藏的。但基本上,std::vector
是这样实现的:
template <class T>
class vector {
public:
vector() : mCapacity(0), mSize(0), mData(0) { }
~vector() { if (mData) delete[] mData; }
...
protected:
int mCapacity;
int mSize;
T *mData;
};
模板
类向量{
公众:
vector():mCapacity(0)、mSize(0)、mData(0){
~vector(){if(mData)delete[]mData;}
...
受保护的:
国际能力;
int-mSize;
T*mData;
};
如您所见,vector
类本身只有几个成员——容量、大小和指向动态分配的内存块的指针,该内存块将存储向量的实际内容
在您的示例中,唯一的区别是这几个字段的存储来自何处。在第一个示例中,存储是从用于包含类的任何存储中分配的——如果它是堆分配的,那么向量的这几位也将是堆分配的。若您的容器是堆栈分配的,那个么向量的那个些位也将是堆栈分配的
在第二个示例中,向量
的那些位始终是堆分配的
在这两个示例中,向量
的实际内容(它的内容)是从堆中分配的,您不能更改它
其他人已经指出,在第二个示例中存在内存泄漏,这也是事实。确保删除容器类的析构函数中的向量。一个实际区别是,在第二个示例中,您从未释放
template <class T>
class vector {
public:
vector() : mCapacity(0), mSize(0), mData(0) { }
~vector() { if (mData) delete[] mData; }
...
protected:
int mCapacity;
int mSize;
T *mData;
};