数组四种类型
栈,堆
qDebug() << "test_stack_heap start";
Entity *entity1 = nullptr;
Entity *const *p = nullptr;
{
MyList myList;
entity1 = new Entity(1, "entity1");
myList.push_back(entity1);
qDebug() << "myList 地址:" << &myList
<< ",数组指针变量地址:" << &myList.at(0)
<< ",数组指针变量指向的内存地址:" << myList.at(0);
// 1.传值
qDebug() << "funcParam";
funcParam(myList);
// 2.传指针
qDebug() << "funcParamPointer";
funcParamPointer(&myList);
// 3.传引用
qDebug() << "funcParamRef";
funcParamRef(myList);
p = &(myList.at(0));
qDebug()<< (**p).id(); // myList被删除前(函数体结束自动删除),可以访问到数组内元素地址,进而获得堆内存里的entity内容
mylist变量存于栈内存,Entity指针变量存于栈内存(数据量大的时候QList会存数据到堆内存),Entity指针指向的Entity内容存于堆内存
生命周期结束后mylist释放,Entity指针变量释放,Entity指针指向的Entity内容不释放(需手动delete)
传参:
- 传值
将mylist的Entity指针变量拷贝复制到list里,此时,list与mylist地址不一样,list的指针变量地址与mylist的指针变量地址不一样,list的指针变量指向的内容与mylist的指针变量指向的内容一样 - 传指针
将mylist的地址作为参数传递,此时只会有地址的拷贝,list的地址与mylist的地址将会一样,指针变量的地址也一样,指针变量指向的内容地址也一样 - 传引用
传引用与传指针一样
栈,栈
qDebug() << "test_stack_stack start";
Entity const *p = nullptr;
{
MyList myList;
Entity entity1(1, "entity1");
myList.push_back(entity1);
qDebug() << "myList 地址:" << &myList << ",数组内容地址:" << &myList.at(0);
// 1.传值
qDebug() << "funcParam";
funcParam(myList);
// 2.传指针
qDebug() << "funcParamPointer";
funcParamPointer(&myList);
// 3.传引用
qDebug() << "funcParamRef";
funcParamRef(myList);
p = &(myList.at(0));
qDebug()<< (*p).id(); // myList被删除前(函数体结束自动删除),可以访问到数组内元素,获得数组存储的entity内容
}
qDebug() << (*p).id(); //此时数组被释放,类指针被释放,无法再通过其访问
qDebug() << "test_stack_stack end";
mylist变量存于栈内存,Entity内容存于栈内存(数据量大的时候QList会存数据到堆内存),生命周期结束后mylist释放,Entity内容释放
传参:
- 传值
将mylist的Entity内容拷贝复制(会拷贝两次,一次是临时变量)到list里,此时,list与mylist地址不一样,list的内容地址与mylist的内容地址不一样 - 传指针
将mylist的地址作为参数传递,此时只会有地址的拷贝,list的地址与mylist的地址将会一样,内容地址也一样 - 传引用
传引用与传指针一样
堆,栈
qDebug() << "test_heap_stack start";
MyList *myList = new MyList;
Entity const *p = nullptr;
{
Entity entity1(1, "entity1");
myList->push_back(entity1);
qDebug() << "myList 地址:" << myList << ",数组内容地址:" << &myList->at(0);
// 1.传值
qDebug() << "funcParam";
funcParam(*myList);
// 2.传指针
qDebug() << "funcParamPointer";
funcParamPointer(myList);
// 3.传引用
qDebug() << "funcParamRef";
funcParamRef(*myList);
p = &(myList->at(0));
}
qDebug() << (*p).id(); //删除myList前,可以访问entity内容
delete myList;
qDebug() << (*p).id(); //删除myList后,无法访问entity内容
qDebug() << "test_heap_stack end";
mylist变量存于堆内存,Entity内容存于栈内存(数据量大的时候QList会存数据到堆内存),mylist需手动释放(释放后Entity内容则自动释放)
传参:
- 传值
将mylist的Entity内容拷贝复制(会拷贝两次,一次是临时变量)到list里,此时,list与mylist地址不一样,list的内容地址与mylist的内容地址不一样 - 传指针
将mylist指针变量作为参数传递,此时只会有地址的拷贝,list的地址与mylist的地址将会一样,内容地址也一样 - 传引用
传引用与传指针一样
堆,堆
qDebug() << "test_heap_heap start";
MyList *myList = new MyList;
Entity *entity1 = nullptr;
Entity *const *p = nullptr;
{
entity1 = new Entity(1, "entity1");
myList->push_back(entity1);
qDebug() << "myList 地址:" << myList
<< ",数组指针变量地址:" << &myList->at(0)
<< ",数组指针变量指向的内存地址:" << myList->at(0);
// 1.传值
qDebug() << "funcParam";
funcParam(*myList);
// 2.传指针
qDebug() << "funcParamPointer";
funcParamPointer(myList);
// 3.传引用
qDebug() << "funcParamRef";
funcParamRef(*myList);
p = &(myList->at(0));
}
qDebug() << (**p).id(); // "删除myList前,可以访问entity内容"
delete myList;
// qDebug() << (**p).id(); //"删除myList后,无法访问entity内容"
qDebug() << entity1->id(); //堆内存Entity内容依然存在
delete entity1;
qDebug() << "test_heap_heap end";
mylist变量存于堆内存,Entity指针变量存于栈内存(数据量大的时候QList会存数据到堆内存),Entity指针指向的Entity内容存于堆内存,mylist需手动释放(释放后Entity指针变量释放,如果Entity指针指向的Entity内容不手动释放,则可能造成内存泄漏),Entity内容需手动释放
传参:
- 传值
将mylist的Entity指针变量拷贝复制到list里,此时,list与mylist地址不一样,list的指针变量地址与mylist的指针变量地址不一样,list的指针变量指向的内容与mylist的指针变量指向的内容一样 - 传指针
将mylist指针变量作为参数传递,此时只会有地址的拷贝,list的地址与mylist的地址将会一样,list的指针变量地址与mylist的指针变量地址一样,list的指针变量指向的内容与mylist的指针变量指向的内容一样 - 传引用
传引用与传指针一样
最后附上代码:
entity
//entity.h
#ifndef ENTITY_H
#define ENTITY_H
#include
#include
class Entity {
public:
Entity();
Entity(int id, QString name);
Entity(const Entity& entity);
Entity& operator=(const Entity& entity);
~Entity();
int id() const;
void setId(int newId);
const QString& name() const;
void setName(const QString& newName);
void sayHello(QString text);
private:
int m_id;
QString m_name;
};
#endif // ENTITY_H
//entity.cpp
#include "entity.h"
#include
Entity::Entity() {
// qDebug() << "Entity construtor";
}
Entity::Entity(int id, QString name) {
this->m_id = id;
this->m_name = name;
// qDebug() << "Entity construtor" << m_id << m_name;
}
Entity::Entity(const Entity &entity) {
this->m_id = entity.m_id;
this->m_name = entity.m_name;
// qDebug() << "Entity copy" << m_id << m_name;
}
Entity &Entity::operator=(const Entity &entity) {
if (this != &entity) {
this->m_id = entity.m_id;
this->m_name = entity.m_name;
}
// qDebug() << "Entity =" << m_id << m_name;
return *this;
}
Entity::~Entity() {
// qDebug() << "Entity delete" << m_id << m_name;
}
int Entity::id() const { return m_id; }
void Entity::setId(int newId) { m_id = newId; }
const QString &Entity::name() const { return m_name; }
void Entity::setName(const QString &newName) { m_name = newName; }
void Entity::sayHello(QString text) { qDebug() << "Entity SayHello!" << text; }
mylist
//mylist.h
#ifndef MYLIST_H
#define MYLIST_H
#include
#include
#include "entity.h"
template
class MyList : public QList {
public:
MyList();
MyList(MyList *myList) {
for (int i = 0; i < myList->length(); i++) {
this->push_back(myList->at(i));
}
}
MyList(MyList &myList) {
for (int i = 0; i < myList.length(); i++) {
this->push_back(myList.at(i));
}
}
~MyList();
};
template
MyList::MyList() : QList() {
// qDebug() << "MyList constrotor";
}
template
MyList::~MyList() {
// qDebug() << "MyList delete";
}
#endif // MYLIST_H
mainwindow
//mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include
#include "entity.h"
#include "mylist.h"
QT_BEGIN_NAMESPACE
namespace Ui {
class MainWindow;
}
QT_END_NAMESPACE
class MainWindow : public QMainWindow {
Q_OBJECT
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
void test_stack_heap();
void test_stack_stack();
void test_heap_stack();
void test_heap_heap();
void test_funcParam();
void funcParam(MyList list);
void funcParamPointer(MyList *list);
void funcParamRef(MyList &list);
void funcParam(MyList list);
void funcParamPointer(MyList *list);
void funcParamRef(MyList &list);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
//mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent), ui(new Ui::MainWindow) {
ui->setupUi(this);
// test_stack_heap(); //栈-堆
// test_stack_stack(); //栈-栈
// test_heap_stack(); //堆-栈
test_heap_heap(); //堆-堆
}
MainWindow::~MainWindow() { delete ui; }
void MainWindow::test_stack_heap() {
qDebug() << "test_stack_heap start";
Entity *entity1 = nullptr;
Entity *const *p = nullptr;
{
MyList myList;
entity1 = new Entity(1, "entity1");
myList.push_back(entity1);
qDebug() << "myList 地址:" << &myList
<< ",数组指针变量地址:" << &myList.at(0)
<< ",数组指针变量指向的内存地址:" << myList.at(0);
// 1.传值
qDebug() << "funcParam";
funcParam(myList);
// 2.传指针
qDebug() << "funcParamPointer";
funcParamPointer(&myList);
// 3.传引用
qDebug() << "funcParamRef";
funcParamRef(myList);
p = &(myList.at(0));
qDebug()
<< (**p)
.id(); // myList被删除前(函数体结束自动删除),可以访问到数组内元素地址,进而获得堆内存里的entity内容
}
// qDebug()
// <<(**p).id();//此时数组被释放,类指针被释放,无法再通过其访问堆内存内容
qDebug() << entity1->id(); //堆内存Entity内容依然存在
delete entity1;
qDebug() << "test_stack_heap end";
}
void MainWindow::test_stack_stack() {
qDebug() << "test_stack_stack start";
Entity const *p = nullptr;
{
MyList myList;
Entity entity1(1, "entity1");
myList.push_back(entity1);
qDebug() << "myList 地址:" << &myList << ",数组内容地址:" << &myList.at(0);
// 1.传值
qDebug() << "funcParam";
funcParam(myList);
// 2.传指针
qDebug() << "funcParamPointer";
funcParamPointer(&myList);
// 3.传引用
qDebug() << "funcParamRef";
funcParamRef(myList);
p = &(myList.at(0));
qDebug()
<< (*p).id(); // myList被删除前(函数体结束自动删除),可以访问到数组内元素,获得数组存储的entity内容
}
qDebug() << (*p).id(); //此时数组被释放,类指针被释放,无法再通过其访问
qDebug() << "test_stack_stack end";
}
void MainWindow::test_heap_stack() {
qDebug() << "test_heap_stack start";
MyList *myList = new MyList;
Entity const *p = nullptr;
{
Entity entity1(1, "entity1");
myList->push_back(entity1);
qDebug() << "myList 地址:" << myList << ",数组内容地址:" << &myList->at(0);
// 1.传值
qDebug() << "funcParam";
funcParam(*myList);
// 2.传指针
qDebug() << "funcParamPointer";
funcParamPointer(myList);
// 3.传引用
qDebug() << "funcParamRef";
funcParamRef(*myList);
p = &(myList->at(0));
}
qDebug() << (*p).id(); //删除myList前,可以访问entity内容
delete myList;
qDebug() << (*p).id(); //删除myList后,无法访问entity内容
qDebug() << "test_heap_stack end";
}
void MainWindow::test_heap_heap() {
qDebug() << "test_heap_heap start";
MyList *myList = new MyList;
Entity *entity1 = nullptr;
Entity *const *p = nullptr;
{
entity1 = new Entity(1, "entity1");
myList->push_back(entity1);
qDebug() << "myList 地址:" << myList
<< ",数组指针变量地址:" << &myList->at(0)
<< ",数组指针变量指向的内存地址:" << myList->at(0);
// 1.传值
qDebug() << "funcParam";
funcParam(*myList);
// 2.传指针
qDebug() << "funcParamPointer";
funcParamPointer(myList);
// 3.传引用
qDebug() << "funcParamRef";
funcParamRef(*myList);
p = &(myList->at(0));
}
qDebug() << (**p).id(); // "删除myList前,可以访问entity内容"
delete myList;
// qDebug() << (**p).id(); //"删除myList后,无法访问entity内容"
qDebug() << entity1->id(); //堆内存Entity内容依然存在
delete entity1;
qDebug() << "test_heap_heap end";
}
void MainWindow::funcParam(MyList list) {
qDebug() << "list 地址:" << &list << ",数组内容地址:" << &list.at(0);
}
void MainWindow::funcParamPointer(MyList *list) {
qDebug() << "list 地址:" << list << ",数组内容地址:" << &list->at(0);
}
void MainWindow::funcParamRef(MyList &list) {
qDebug() << "list 地址:" << &list << ",数组内容地址:" << &list.at(0);
}
void MainWindow::funcParam(MyList list) {
qDebug() << "list 地址:" << &list << ",数组指针变量地址:" << &list.at(0)
<< ",数组指针变量指向的内存地址:" << list.at(0);
}
void MainWindow::funcParamPointer(MyList *list) {
qDebug() << "list 地址:" << list << ",数组指针变量地址:" << &list->at(0)
<< ",数组指针变量指向的内存地址:" << list->at(0);
}
void MainWindow::funcParamRef(MyList &list) {
qDebug() << "list 地址:" << &list << ",数组指针变量地址:" << &list.at(0)
<< ",数组指针变量指向的内存地址:" << list.at(0);
}