Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/159.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++ 什么';这两门课的区别是什么?_C++_Memory - Fatal编程技术网

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方法的访问具有不同的语法:)


在第一种情况下,std::vector被直接放入类中(它正在处理任何内存分配和释放,它需要增加和缩小向量,并在对象被破坏时释放内存;它正在从您那里抽象内存管理,以便您不必处理它)。在第二种情况下,您在堆中的某个位置显式地为std::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;
};