Russian Qt Forum
Ноябрь 25, 2024, 04:55 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: 1 [2]   Вниз
  Печать  
Автор Тема: Контейнеры и куда девается память  (Прочитано 11405 раз)
Lagovas
Гость
« Ответ #15 : Август 11, 2012, 21:17 »

Не, уже не покажу... Поправил оказывается давно. А добавлял типа так вроде,
Цитировать
QPoint* p = new Point(x,y);
varPolygon.append(*p);
Если не лень и будет время, просмотрите код который сделал. Игра змейка, интересны моменты по утечкам, ну и замечания по другому быдлокоду. Ибо игра писалась не ради игры, а ради практики работы с памятью. Два основных класса game и snake. Еще один отвечает за отрисовку, но там вроде ничего сложного.
П.С. Еще вопрос напоследок, если в классе обьявить поле SomeClass c; Память выделиться под эту переменную сразу через конструктор по умолчанию или нет? Или только если в конструкторе класса где обьявляем поле напишем
c=SomeClass()? Смотрел в книгах, там часто обьявляют в классе простые классы, где нету конструкторов с аргументами, что бы приметить как они и где инициализируются. Знаю что такое поле освободится само после удаления обьекта которому принадлежит, в отличие от случая, если обьявить SomeClass*.
Из-за неуверенности того как работает, в своем коде обьявлял в основном через указатели, хотя если через обычное обьявление, оно упростит управление памятью...
Snake.h
Код:
#ifndef SNAKE_H
#define SNAKE_H
#include <QObject>
#include <QQueue>
#include <QPoint>
class QPolygon;

class Snake : public QObject
{
    Q_OBJECT

public:
    enum Direction {Left, Right, Top, Bottom};
    Snake();
    ~Snake();

    QPoint getTail();
    QPoint getHead();
    void setHead(QPoint&);
    int getCountBlocks();
    int getLength();
    const QPolygon* getBlockPositions();
    Direction getDirection();

    void Reset();
    void MoveToLeft();
    void MoveToRight();
    void MoveToTop();
    void MoveToBottom();
    bool Move();
    void AddBlock();
    void ChangeDirection(Direction);

signals:
    void onBlockAddFinish(QPoint);


private:
    QQueue<QPoint>* addedBlocks;
    QPolygon* blockPositions;
    Direction direction;
    void MoveBlocks();
    void CreateStandartSnake();
    bool isCollisionOfSnake();
    void Initialize();
};

#endif // SNAKE_H
Snake.cpp
Код:
#include "snake.h"
#include <QQueue>
#include <QPoint>
#include <QPolygon>
#include <QMessageBox>

Snake::Snake()
{
    Initialize();
}

void Snake::Initialize()
{
    addedBlocks = new QQueue<QPoint>();
    blockPositions = new QPolygon();
    CreateStandartSnake();
    direction = Right;
}

Snake::~Snake()
{
    delete addedBlocks;
    delete blockPositions;
}

void Snake::MoveBlocks()
{
    bool newBlock = false;
    //time to add new block to snake
    if(addedBlocks->count() > 0 && getTail() == addedBlocks->head())
    {
        newBlock = true;
    }

    for(int i = getLength() - 1; i != 0; i--)
    {
        blockPositions->setPoint(i, blockPositions->point(i-1));
    }

    if (newBlock)
    {
        blockPositions->append(addedBlocks->dequeue());
        emit this->onBlockAddFinish(getTail());
    }
}

void Snake::Reset()
{
    blockPositions->clear();
    addedBlocks->clear();
    Initialize();
}

void Snake::CreateStandartSnake()
{
    blockPositions->append(QPoint(2,0));
    blockPositions->append(QPoint(1,0));
    blockPositions->append(QPoint(0,0));
}

bool Snake::Move()
{
    MoveBlocks();
    switch (direction)
    {
    case Left:
        MoveToLeft();
        break;
    case Right:
        MoveToRight();
        break;
    case Bottom:
        MoveToBottom();
        break;
    case Top:
        MoveToTop();
        break;
    }
    return isCollisionOfSnake();
}

bool Snake::isCollisionOfSnake()
{
    QPoint head = getHead();
    for (int i = 1; i < getLength(); i++)
    {
        if (head == blockPositions->point(i))
        {
            return false;
        }
    }
    return true;
}

void Snake::ChangeDirection(Direction direct)
{
    if ((direction == Left && direct == Right) || (direction == Right && direct == Left))
    {
        return;
    }
    if ((direction == Top && direct == Bottom) || (direction == Bottom && direct == Top))
    {
        return;
    }
    direction = direct;
}

void Snake::setHead(QPoint &point)
{
    blockPositions->setPoint(0,point);
}

void Snake::AddBlock()
{
    addedBlocks->enqueue(getHead());
}

void Snake::MoveToLeft()
{
    QPoint head = getHead();
    head.rx()--;
    blockPositions->setPoint(0,head);
}

void Snake::MoveToRight()
{
    QPoint head = getHead();
    head.rx()++;
    blockPositions->setPoint(0,head);
}

void Snake::MoveToTop()
{
    QPoint head = getHead();
    head.ry()--;
    blockPositions->setPoint(0,head);
}

void Snake::MoveToBottom()
{
    QPoint head = getHead();
    head.ry()++;
    blockPositions->setPoint(0, head);
}

QPoint Snake::getTail()
{
    return blockPositions->point(getLength()-1);
}

QPoint Snake::getHead()
{
    return blockPositions->point(0);
}

int Snake::getCountBlocks()
{
    return blockPositions->count() + addedBlocks->count();
}

int Snake::getLength()
{
    return blockPositions->count();
}

const QPolygon* Snake::getBlockPositions()
{
    return blockPositions;
}

Snake::Direction Snake::getDirection()
{
    return direction;
}
Game.h
Код:
#ifndef GAME_H
#define GAME_H
#include <QObject>
#include "snake.h"
#include "IBlockDraw.h"
#include <QQueue>
#include <QKeyEvent>
#include <QBrush>
#include "statistic.h"
class QPoint;
class QTimer;

class Game : public QObject
{
    Q_OBJECT
public:
    enum Speed {Slow = 200, Medium = 100, Fast = 50};
    Game(int width, int height, IBlockDraw* BlockDraw);
    ~Game();
    int getPoints();
    void Start();
    void End();
    void setSnakeColor(const QBrush&);
    void setBlockColor(const QBrush&);
    void setBackgroundColor(const QBrush&);
    Statistic* getStatistic();
    void KeyPressHandle(QKeyEvent *);
    Speed getSpeed();
    void setSpeed(Speed);
    Snake* snake;
    void SaveResult(QString&);

protected:
    bool isNewBlock();
    void AddNewBlock();

private:
    int points;
    QTimer* moveTimer;
    QQueue<Snake::Direction>* pressedDirections;
    QPoint* block;
    QBrush* backgroundColor;
    QBrush* snakeColor;
    QBrush* blockColor;
    IBlockDraw* blockDraw;
    Statistic statistic;
    int eatPoints;
    int width;
    int height;
    Speed speed;

    bool Move();
    void NewBlock();
    void ClearBlock(const QPoint&);
    void DrawSnakeBlock(const QPoint&);
    void DrawBlock();
    void Draw(const QPoint&, const QBrush&);
    void DrawSnake();
    void DrawBackground();
    void setPoints(int points);
    void AddPoints(int);
    void CheckSnakeOutOfMap();

public slots:
    void MoveByTime();
    void AddSnakeBlockFinish(const QPoint&);


signals:
    void onPointsChanged(int points);
    void onGameOver();
    void onSnakeBlockCountChanged(int legth);

};

#endif // GAME_H
Game.cpp
Код:
#include "game.h"
#include <QPoint>
#include <QTimer>
#include <QBrush>
#include <QQueue>
#include "snake.h"
#include <QDateTime>


Game::Game(int width, int height, IBlockDraw *BlockDraw)
{
    QString path("statistic.db");
    statistic = Statistic(path);
    eatPoints = 100;
    this->width = width;
    this->height = height;
    blockDraw = BlockDraw;
    moveTimer = new QTimer(this);
    moveTimer->setInterval(Slow);
    moveTimer->stop();
    snake = new Snake();
    backgroundColor = new QBrush(Qt::gray);
    snakeColor = new QBrush(Qt::blue);
    blockColor = new QBrush(Qt::red);
    pressedDirections = new QQueue<Snake::Direction>();
    QObject::connect(moveTimer, SIGNAL(timeout()), this, SLOT(MoveByTime()));
    QObject::connect(snake, SIGNAL(onBlockAddFinish(QPoint)), this, SLOT(AddSnakeBlockFinish(const QPoint&)));
}

Game::~Game()
{
    delete snake;
    delete moveTimer;
    delete pressedDirections;
    delete block;
    delete backgroundColor;
    delete blockColor;
    delete snakeColor;
    delete blockDraw;
}

void Game::Start()
{
    snake->Reset();
    DrawBackground();
    DrawSnake();
    points = 0;
    moveTimer->start();
    //emit onSnakeBlockCountChanged(snake->getCountBlocks());
    NewBlock();
}

void Game::End()
{
    moveTimer->stop();
    //clearing old directions for new game
    pressedDirections->clear();
    pressedDirections = new QQueue<Snake::Direction>();
    emit onGameOver();
}

bool Game::isNewBlock()
{
    QPoint head = snake->getHead();
    if(head.x()== block->x() && head.y() == block->y())
    {
        return true;
    }
    return false;
}

void Game::AddNewBlock()
{
    snake->AddBlock();
    AddPoints(eatPoints);
    NewBlock();
    emit onSnakeBlockCountChanged(snake->getCountBlocks());
}

void Game::MoveByTime()
{
    Move();
}

bool Game::Move()
{
    if (pressedDirections->count() > 0)
    {
        snake->ChangeDirection(pressedDirections->dequeue());
    }

    ClearBlock(snake->getTail());
    if(!snake->Move())
    {
        End();
        return false;
    }

    CheckSnakeOutOfMap();

    if(isNewBlock())
    {
        AddNewBlock();
    }

    DrawSnakeBlock(snake->getHead());
    return true;
}

void Game::NewBlock()
{
    bool contains = false;
    qsrand(QDateTime::currentMSecsSinceEpoch());
    //checking that place new block not on snake
    do
    {
        contains = false;
        block = new QPoint(qrand() % width, qrand() % height);
        if (snake->getBlockPositions()->contains(*block))
        {
            contains = true;
            delete block;
        }
    }
    while(contains);
    DrawBlock();
}

void Game::Draw(const QPoint& point, const QBrush& color)
{
    int x = point.x() * blockDraw->getSize();//+1;
    int y = point.y() * blockDraw->getSize();//+1;
    QPoint p(x,y);
    blockDraw->DrawBlock(p, color);
}

void Game::ClearBlock(const QPoint& p)
{
    Draw(p, *backgroundColor);
}

void Game::DrawSnakeBlock(const QPoint& p)
{
    Draw(p, *snakeColor);
}

void Game::DrawBlock()
{
    Draw(*block, *blockColor);
}

void Game::AddSnakeBlockFinish(const QPoint& block)
{
    DrawSnakeBlock(snake->getTail());
}

void Game::DrawSnake()
{
    const QPolygon* snakeBlocks = snake->getBlockPositions();
    for(int i=0; i<snake->getCountBlocks(); i++)
    {
        DrawSnakeBlock(snakeBlocks->point(i));
    }
}

void Game::DrawBackground()
{
    QPoint point;
    for (int i = 0; i < width+1; i++)
    {
        for (int j = 0; j < height+1; j++)
        {
            point.rx()=i;
            point.ry()=j;
            Draw(point, *backgroundColor);
        }
    }
}

void Game::setPoints(int points)
{
    this->points = points;
    emit onPointsChanged(points);
}

void Game::AddPoints(int points)
{
    this->points+=points;
    emit onPointsChanged(this->points);
}

void Game::setSpeed(Game::Speed sp)
{
    speed = sp;
    moveTimer->setInterval(speed);
}

Game::Speed Game::getSpeed()
{
    return speed;
}

void Game::KeyPressHandle(QKeyEvent* e)
{
    switch (e->key())
    {
    case Qt::Key_Up:
    case Qt::Key_W:
        pressedDirections->enqueue(Snake::Top);
        break;
    case Qt::Key_Left:
    case Qt::Key_A:
        pressedDirections->enqueue(Snake::Left);
        break;
    case Qt::Key_Down:
    case Qt::Key_S:
        pressedDirections->enqueue(Snake::Bottom);
        break;
    case Qt::Key_Right:
    case Qt::Key_D:
        pressedDirections->enqueue(Snake::Right);
        break;
    }
}

void Game::CheckSnakeOutOfMap()
{
    QPoint head = snake->getHead();
    if(head.x() > width)
    {
        QPoint* point = new QPoint(0,head.y());
        snake->setHead(*point);
    }
    if(head.x() < 0)
    {
        QPoint* point = new QPoint(width,head.y());
        snake->setHead(*point);
    }
    if(head.y() > height)
    {
        QPoint* point = new QPoint(head.x(),0);
        snake->setHead(*point);
    }
    if(head.y() < 0)
    {
        QPoint* point = new QPoint(head.x(),height);
        snake->setHead(*point);
    }
}

Statistic * Game::getStatistic()
{
    return &statistic;
}

void Game::setSnakeColor(const QBrush& color)
{
    *snakeColor = color;
}

void Game::setBlockColor(const QBrush& color)
{
    *blockColor = color;
}

void Game::setBackgroundColor(const QBrush& color)
{
    *backgroundColor = color;
}

void Game::SaveResult(QString &name)
{
    statistic.AddRecord(name, points, QDate::currentDate());
}
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #16 : Август 12, 2012, 10:49 »

Не, уже не покажу... Поправил оказывается давно. А добавлял типа так вроде,
Цитировать
QPoint* p = new Point(x,y);
varPolygon.append(*p);
Так просто утечка, 2 копии данных, одна создана new, др. скопирована в контейнер. Первая не удаляется.

П.С. Еще вопрос напоследок, если в классе обьявить поле SomeClass c; Память выделиться под эту переменную сразу через конструктор по умолчанию или нет?
Память для объекта и всех его членов (и членов членов) выделяется сразу и еще до того как управление передается конструктору. Размер этой памяти = sizeof(A).

Если не лень и будет время, просмотрите код который сделал. Игра змейка, интересны моменты по утечкам, ну и замечания по другому быдлокоду.
Посмотрю когда буду посвободнее
Записан
Lagovas
Гость
« Ответ #17 : Август 12, 2012, 11:07 »

Цитировать
Память для объекта и всех его членов (и членов членов) выделяется сразу и еще до того как управление передается конструктору. Размер этой памяти = sizeof(A).
А как тогда создать так обьект через конструктор с параметрами? Если писать
Код:
class A{
B b(args)
}
то жалуется.
И еще маленький такой вопрос, когда требуется ссылка в аргументе, как правильно сделать вроде такого:
Код:
void foo(QString&);
void main()
{
    foo(QString(""));
}
Жалуется что получается QString вместо Qstring&. Если писать &QString(""), жалуется что получил указатель вместо ссылки. В итоге приходится создавать переменную, задавать значение и ее уже передавать. Конечно же лучше переменная, ибо ее имя может передавать смысл и самодокументирование кодом получается, но иногда нужно задать в параметр значения по умолчанию и удобно просто передать созданный обьект через пустой конструктор.
Заранее благодарен.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #18 : Август 12, 2012, 12:19 »

А как тогда создать так обьект через конструктор с параметрами? Если писать
Код:
class A{
B b(args)
}
то жалуется.
Примеры
Код
C++ (Qt)
class MyClass {
public:
MyClass( const QString & txt = "" ) : mName(txt) {}
 
QString mName;
};
 
class MyClass2 {
public:
MyClass( const QString & txt = "" ) : mStruct(str) {}
 
MyStruct mStruct;
};
 

И еще маленький такой вопрос, когда требуется ссылка в аргументе, как правильно сделать вроде такого:
Код:
void foo(QString&);
void main()
{
    foo(QString(""));
}
Жалуется что получается QString вместо Qstring&. Если писать &QString(""), жалуется что получил указатель вместо ссылки. В итоге приходится создавать переменную, задавать значение и ее уже передавать. Конечно же лучше переменная, ибо ее имя может передавать смысл и самодокументирование кодом получается, но иногда нужно задать в параметр значения по умолчанию и удобно просто передать созданный обьект через пустой конструктор.
Заранее благодарен.
Это уже проходили выше, нужна константная ссылка
Код
C++ (Qt)
void foo(const QString & str = "");
}
Записан
Lagovas
Гость
« Ответ #19 : Август 12, 2012, 12:32 »

Код:
class MyClass {
public:
 MyClass( const QString & txt = "" ) : mName(txt) {}
 
 QString mName;
};
 
class MyClass2 {
public:
 MyClass( const QString & txt = "" ) : mStruct(str) {}
 
 MyStruct mStruct;
};
То ли я дурак, то ли Вы опечатались где то. Во втором классе должно быть по ходу
Код:
class MyClass2{
public:
    MyClass(const QString& text = ""):mClass(str){}
MyClass mClass;
}
Это насколько я понял. Значит если поле обьект и его нужно создавать не через стандартный конструктор, то нужно инициализировать через аргументы конструктора, и никак иначе? Т.е. если в конструктор обьекта не передается параметр которым должен инициализироваться обьект-член, то нужно тогда его указателем делать и в конструкторе самому создавать? Ну и следить за удалением конечно же через деструктор. Пример например
Код:
class MyClass
{
 public:
    MyClass(int score): score(score){}
    MyClass():score(0){}
 int score;
}
class MyClass2
{
 public MyClass2(QString& s = ""):myStr(s){}
QString myStr;
MyClass mClass;
}
В этом случае получается нельзя обьявить обьект класса MyClass полем обьекта класса MyClass2 так, что бы он создавался через конструктор принимающий параметр int, если его не принимать как параметр конструктора класса MyClass2 и не инициализировать типа :mClass(intValue)?
Заранее благодарен.
П.С. Спасибо большое, уже стало яснее с параметрами.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #20 : Август 12, 2012, 13:21 »

То ли я дурак, то ли Вы опечатались где то. Во втором классе должно быть по ходу
Код:
class MyClass2{
public:
    MyClass(const QString& text = ""):mClass(str){}
MyClass mClass;
}
Не вижу опечатки, Вы просто поменяли имя члена

Значит если поле обьект и его нужно создавать не через стандартный конструктор, то нужно инициализировать через аргументы конструктора, и никак иначе?
Если Вы не указываете никаких конструкторов, то будет создан по умолчанию. Однако если Вы написали конструктор(ы) с параметром, то конструктор без параметров не создается. Такой объект нельзя будет поместить в контейнер. Такой объект может быть членом до класса, но тот в своем конструкторе обязан будет вызвать конструктор этого члена с параметром. Смысл простой - невозможно создать объект минуя конструктор (ну почти), поэтому если конструктор с параметрами - он вызывается при создании.

Конструктор с параметрами по умолчанию (всеми) считается конструктором по умолчанию, это удобно и часто используется. Если член имеет 2 или более конструктора, то в конструкторе вмещающего класса можно указать любой из них. Если ничего не указано, член инициализируется его конструктором по умолчанию.
Записан
Lagovas
Гость
« Ответ #21 : Август 12, 2012, 13:43 »

Что будет в этом случае?
Код:
class Foo
{
public:
    Foo(const QString&s):str(s){}
    QString str;
};

class Foo2
{
public:
    Foo2(){
        foo = Foo(QString("foo"));
    }
    Foo foo;
};
Что произойдет в этом коде? Тут выдает ошибку что не находит конструктор без параметров. Что бы исправить эту ошибку, я так понял можно максимум сделать
Код:
Foo2():foo(QString("foo")){...}
верно? Т.е. если там параметром должно принимать какой нить обьект посложнее, который нужно проинициализировать, все поля задать, т.е. простым созданием на месте не обойтись, то тогда нужно обьявлять Foo*? Иначе через просто Foo мы не сможем в самом конструкторе инициализировать, а через :field() будет говнокод, ибо много инициализаций придется втулить в параметры конструктора сложного Foo?
Заранее благодарен.
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #22 : Август 12, 2012, 14:14 »

Правильно инициализировать член не в теле конструктора, а в списке инициализаторов (после двоеточия)
Код
C++ (Qt)
class Foo2
{
public:
   Foo2() : foo(QString("foo"))
//  Foo2() : foo("foo")                // можно и так
   {
   }
   Foo foo;
};
 

Записан
Lagovas
Гость
« Ответ #23 : Август 12, 2012, 14:19 »

Это я понял, я лишь уточняю, по другому никак? Просто если там у Foo будет конструктор типа (HardObject&, HardObject2&...) которые тоже инициализируется различными аргументами то получится что то вроде :foo(HardObject(Param1(), Param2()), HardObject2(...)), и что бы такого бардака не было, в таком случае уже лучше указатель делать членом класса, да?
Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #24 : Август 12, 2012, 15:53 »

Это я понял, я лишь уточняю, по другому никак? Просто если там у Foo будет конструктор типа (HardObject&, HardObject2&...) которые тоже инициализируется различными аргументами то получится что то вроде :foo(HardObject(Param1(), Param2()), HardObject2(...)), и что бы такого бардака не было, в таком случае уже лучше указатель делать членом класса, да?
Нет, использовать член-указатель или член-объект определяется др соображениями. Просто сделайте у классов-членов конструкторы по умолчанию - и тогда уже можно и в теле конструктора ими заниматься
Записан
Lagovas
Гость
« Ответ #25 : Август 14, 2012, 01:06 »

Спасибо. Начал читать по поводу ссылок, передачу как аргументов и т.п. и назрел вопрос.
Код:
void f(Type* t){};
void main(){
f(new Type());
}
Как я понимаю, в этом коде происходит следующее. Создается в куче обьект класса Type (тут все понятно), возвращается указатель на этот обьект. Т.е. после вызова new Type() мы получаем временный обьект Type*. Его значение (ссылка на обьект в куче) копируется в локальную переменную t функции f (действующую в ее области видимости), после этого что происходит - этот временный указатель возвращенный через new удаляется из-за выхода из области или нет? До куда его область видимости, до конца функции или сразу как скопируется в параметр функции удаляется? По идее, как все временные обьекты, должен удалиться сразу после закрывающей скобки ")" в вызове функции, либо же до закрывающей "}"?
Из-за чего вопрос. Ведь если функция принимает const type&, то можно передать временный обьект, его ссылка скопируется (только ссылка, не сам обьект), он удалится и ссылка указывает на пустое место?

В целом в чем заключается вопрос. Какая область видимости временного обьекта передаваемого как параметр? До конца функции или до ")"?
Искал в Эккеле, страуструпе... не нашел что бы черным по белому рассказывалось, что живут вот до сюда. По логике конечно живут до конца функции, но все же из-за того что я новенький в плюсах, не уверен пока более опытные не подтвердят. Сам попробовал проверить это с помощью простого кода, все вроде сходится. Кстати вопрос по коду еще:
Код:
#include <QtCore/QCoreApplication>
#include <QDebug>
#include "windows.h"

class Record{
public:
    int x;//т.к. тест, то всеравно где
    Record()
    {
        x=3;
        qDebug("record created");
    }
    ~Record()
    {
        qDebug("record destructed");
    }
    Record(const Record& r)
    {
        qDebug() << "copy constructor";
    }
};

static Record* r;//будем хранить ссылку передаваемую в функцию

void Test(const Record& rec){
    qDebug("Test start");
    //qDebug()<<"&rec="<<&rec;
    if(&(*r) != &rec)//если новая ссылка не равна старой, выводим и присваиваем
    {
     qDebug()<<"&rec="<<&rec;
     r = const_cast<Record*>(&rec);
    }
    QString s("ldgjfdklgjdfg"), ss("fsfsdfdsfsdf");
    for (int i = 0; i < 10000000; i++)
    {
        s+=ss;//что бы было какое то время для удаления временного обьекта если должен удаляться
    }
    Sleep(1000);//с той же целью
    qDebug("Test end");
}


int main(int argc, char *argv[]){
    QCoreApplication a(argc, argv);
    for(int i=0; i<10; i++)
    {
        Test(Record());
        Sleep(1000);//время что бы могла освободиться память временных обьектов и т.п.
    }
    return a.exec();
}
В итоге постоянно выводится одна и та же ссылка. Это нормально или нет? Это так хорошо с организацией памяти что каждый раз создает обьект в том же месте, или это просто ссылка на тоже место в стеке (стек ведь не меняется в программе, а расположение параметра всегда в том же есте)?
Заранее благодарен.
« Последнее редактирование: Август 14, 2012, 01:26 от Lagovas » Записан
Igors
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 11445


Просмотр профиля
« Ответ #26 : Август 14, 2012, 02:16 »

Т.е. после вызова new Type() мы получаем временный обьект Type*. Его значение (ссылка на обьект в куче) копируется в локальную переменную t функции f (действующую в ее области видимости), после этого что происходит - этот временный указатель возвращенный через new удаляется из-за выхода из области или нет?
Никакой ссылкой в приведенном Вами коде и не пахнет. Вообще "ссылка" - это условное понятие, "физически" никаких ссылок нет, есть структуры и их адреса  - все. Вот от этой печки и пляшите.
Код
C++ (Qt)
foo(new Record());  // foo( const Record * );
 
Создали в куче объект, new вернул указатель на него (адрес). Грубо: после выполнения new адрес сидит в регистре eax. Толкнули этот адрес на стек (push eax) и вызвали foo (call [foo]). Ф-ция отработала и вернула управление. Вероятно подровняли стек (add, sp, 4) и все, никаких удалений не производится. Если ф-ция объект не удалила, он так в куче и будет.

Теперь пресловутая ссылка
Код
C++ (Qt)
fooRef(Record());  // fooRef( const Record & );
 
На стеке отвели место для безымянного Record и вызвали его конструктор. Возможно конструктор там какие-то члены создал в куче - то его дело. Толкнули опять-таки адрес Record на стек и вызвали ф-цию. Ф-ция отработала и вернула упрвление. Вызываем деструктор Record (если есть). Выравниваем стек. Готовченко.

Что неясно?

« Последнее редактирование: Август 14, 2012, 02:22 от Igors » Записан
Lagovas
Гость
« Ответ #27 : Август 14, 2012, 08:16 »

Извиняюсь, в первом коде должно было быть const Type&, 2 часа ночи дали о себе знать...
Код:
На стеке отвели место для безымянного Record и вызвали его конструктор. Возможно конструктор там какие-то члены создал в куче - то его дело. Толкнули опять-таки адрес Record на стек и вызвали ф-цию. Ф-ция отработала и вернула упрвление. Вызываем деструктор Record (если есть). Выравниваем стек. Готовченко.
Значит область действия этого временного обьекта до конца функции, что и хотел узнать. Спасибо.
Записан
Страниц: 1 [2]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.143 секунд. Запросов: 23.