Форум программистов, компьютерный форум CyberForum.ru

Вылет программы с классом своего стека - C++

Восстановить пароль Регистрация
 
Woloc Graube
0 / 0 / 0
Регистрация: 09.02.2013
Сообщений: 18
17.01.2014, 17:00     Вылет программы с классом своего стека #1
Здравствуйте. Вот начинаю изучать ООП и надо написать стек. Набросал чуток кода, написал push() и printStack(). Тестирую их, ошибок явных нету, но вот программа вылетает. Дебаггер показал, что стек не заполняется. Пробовал получить доступ к 0-элементу: вылетает так же.
Вот код:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
#pragma once
namespace wg{
 
    template <typename stackType> 
    class stack
    {
    private:
        stackType* _stack;
        int tos;
        int _size;
    public:
        stack(int = 8);
        ~stack(void);
 
        void push(stackType);
        void printStack(void);
    };
 
}
 
//опис
 
template <typename stackType>
wg::stack <stackType>::stack(int stackSize)
{
    tos = -1;
    _size = stackSize ? stackSize : 8;
    _stack = new stackType(_size);
}
 
template <typename stackType>
wg::stack <stackType>::~stack(void)
{
    delete [] _stack;
}
 
template <typename stackType>
void wg::stack <stackType>::push(stackType _p)
{
    if (tos == _size - 1)
    {
        std::cout << "Stack overflow!" << std::endl;
        return;
    }
    tos++;
    _stack[tos] = _p;
}
 
template <typename stackType>
void wg::stack <stackType>::printStack()
{
    int i = 0;
    while (i < tos)
    {
        std::cout << _stack[i] << std::endl;
        i++;
    }
}
C++ (Qt)
1
2
3
4
5
6
7
8
9
void main()
{
    wg::stack<int> a(10);
    a.push(5);
    a.push(5);
    a.push(6);
    a.printStack();
    std::cin.get();
}
Что может бьіть? За код сильно не ругайте, учусь только :-)
После регистрации реклама в сообщениях будет скрыта и будут доступны все возможности форума.
Убежденный
Системный программист
 Аватар для Убежденный
14197 / 6212 / 985
Регистрация: 02.05.2013
Сообщений: 10,353
Завершенные тесты: 1
17.01.2014, 17:19     Вылет программы с классом своего стека #2
Строка 28:
C++
1
_stack = new stackType(_size);
Должно быть так:
C++
1
_stack = new stackType[_size];
Woloc Graube
0 / 0 / 0
Регистрация: 09.02.2013
Сообщений: 18
17.01.2014, 17:21  [ТС]     Вылет программы с классом своего стека #3
Вот я затупил-то.
Спасибо огромное) Даже стьідно за такую ошибку :-)
Убежденный
Системный программист
 Аватар для Убежденный
14197 / 6212 / 985
Регистрация: 02.05.2013
Сообщений: 10,353
Завершенные тесты: 1
17.01.2014, 17:29     Вылет программы с классом своего стека #4
Цитата Сообщение от Woloc Graube Посмотреть сообщение
За код сильно не ругайте, учусь только :-)
Пара моментов.

1) Передавайте аргументы по ссылке или указателю. А если они не изменяются
внутри функции или метода - делайте их const. И методы тоже можно (и нужно)
делать const, если они не изменяют поля класса.

Например:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Было:
 
template <typename stackType>
void wg::stack <stackType>::push(stackType _p)
 
// Стало:
 
template <typename stackType>
void wg::stack <stackType>::push(stackType const & _p)
 
// ...
 
// Было:
 
template <typename stackType>
void wg::stack <stackType>::printStack()
 
// Стало:
 
template <typename stackType>
void wg::stack <stackType>::printStack() const
 
// Не забываем поправить объявления методов :)
2) Инициализацию полей класса лучше по возможности выносить в
списки инициализации:

C++
1
2
3
4
5
6
7
template <typename stackType>
wg::stack <stackType>::stack(int stackSize) :
    tos(-1),
    _size(stackSize ? stackSize : 8),
    _stack(new stackType(_size))
{
}
Учтите, что поля инициализируются в том порядке, в котором они объявлены в классе.
В Вашем примере _stack в объявлении класса нужно сместить вниз, под tos и _size.

3) Если класс копируемый, его нужно обеспечить конструктором копирования и
оператором присваивания. Если нет - эти члены следует объявить закрытыми, не
предоставив реализации (в C++11 есть для этих целей delete, но это другая тема).
Woloc Graube
0 / 0 / 0
Регистрация: 09.02.2013
Сообщений: 18
17.01.2014, 22:41  [ТС]     Вылет программы с классом своего стека #5
Спасибо огромное за советы!
А то, что мы будем передавать аргументы по ссылке дает повышение производительности или еще что-то?
Убежденный
Системный программист
 Аватар для Убежденный
14197 / 6212 / 985
Регистрация: 02.05.2013
Сообщений: 10,353
Завершенные тесты: 1
17.01.2014, 23:01     Вылет программы с классом своего стека #6
Когда вы передаете объект по указателю или ссылке, вы избегаете создания его копий.
Для таких простых объектов, как int или bool, эта экономия несущественна, но как только
дело коснется сложных объектов, выигрыш будет заметен (особенно в критичных к
скорости местах). Ну а const - это просто "лекарство", превентивная мера от случайной
модификации параметра там, где этого происходить не должно. const не влечет
никаких накладных расходов, но чрезвычайно полезен.
Woloc Graube
0 / 0 / 0
Регистрация: 09.02.2013
Сообщений: 18
17.01.2014, 23:09  [ТС]     Вылет программы с классом своего стека #7
Спасибо! Никогда не задумывался об таких вещах. Да и нигде никто не рассказывал.
Действительно, полезные вещи Вы мне рассказали
Убежденный
Системный программист
 Аватар для Убежденный
14197 / 6212 / 985
Регистрация: 02.05.2013
Сообщений: 10,353
Завершенные тесты: 1
17.01.2014, 23:13     Вылет программы с классом своего стека #8
Цитата Сообщение от Woloc Graube Посмотреть сообщение
Спасибо! Никогда не задумывался об таких вещах. Да и нигде никто не рассказывал.
Это все есть в книгах по языку С++.
Вот сюда загляните: Литература C++
alsav22
5282 / 4801 / 442
Регистрация: 04.06.2011
Сообщений: 13,587
18.01.2014, 01:27     Вылет программы с классом своего стека #9
Цитата Сообщение от Убежденный Посмотреть сообщение
2) Инициализацию полей класса лучше по возможности выносить в
списки инициализации:
Убежденный, можете пояснить, чем это, именно, лучше?
Убежденный
Системный программист
 Аватар для Убежденный
14197 / 6212 / 985
Регистрация: 02.05.2013
Сообщений: 10,353
Завершенные тесты: 1
18.01.2014, 03:05     Вылет программы с классом своего стека #10
Цитата Сообщение от alsav22 Посмотреть сообщение
Убежденный, может пояснить, чем это, именно, лучше?
Да, безусловно. Конкретное понимание всегда лучше заученных "догм",
просто я надеюсь, топикстартер сам найдет ответы в правильных книжках.

Доводы в пользу списков инициализации.

1) Списки инициализации позволяют оптимизировать конструирование.

Если поле класса инициализируется обычным "старым дедовским" способом, через
присваивание ему значения в теле конструктора, то для него сначала вызывается
конструктор по умолчанию, а потом оператор присваивания.
Если же инициализировать поле класса с помощью списка инициализации, то оно
будет сконструировано в один присест, через соответствующий конструктор.
Обычно это конструктор копирования или другой конструктор с аргументами.
То есть, получается в итоге одна операция вместо двух.

2) Константные и ссылочные поля класса, а также конструкторы базовых классов,
можно инициализировать только с помощью списков инициализации.

Доводы против списков инициализации.

1) Поля класса инициализируются в том порядке, в котором они объявлены в классе, а
не в том, в котором они перечислены в списке инициализации. Это создает почву для
ошибок, если поля имеют зависимости друг от друга.

2) Усложняется написание безопасного по отношению к исключениям кода.
gromo
 Аватар для gromo
366 / 265 / 24
Регистрация: 04.09.2009
Сообщений: 1,214
18.01.2014, 03:10     Вылет программы с классом своего стека #11
Цитата Сообщение от Убежденный Посмотреть сообщение
1) Поля класса инициализируются в том порядке, в котором они объявлены в классе, а не в том, в котором они перечислены в списке инициализации. Это создает почву для ошибок, если поля имеют зависимости друг от друга.
Даже если и не будет зависимостей, хороший компилятор обязан выдать предупреждение, так что не такой уж и минус
Убежденный
Системный программист
 Аватар для Убежденный
14197 / 6212 / 985
Регистрация: 02.05.2013
Сообщений: 10,353
Завершенные тесты: 1
18.01.2014, 12:50     Вылет программы с классом своего стека #12
Цитата Сообщение от gromo Посмотреть сообщение
хороший компилятор обязан выдать предупреждение
По стандарту не обязан, насколько я знаю:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
#include <iostream>
 
 
 
struct foo
{
    foo(int v) : a(v), b(a + 1) { std::cout << b << std::endl; }
 
    int b;
    int a;
};
 
 
 
int main()
{
    foo Foo(5);
    return 0;
}
Онлайн-компилятор ideone (C++11 и C++4.8.1) спокойно проглатывает этот код.
Visual C++ 2008/2010 тоже.
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
19.01.2014, 16:32     Вылет программы с классом своего стека #13
Цитата Сообщение от Убежденный Посмотреть сообщение
Если поле класса инициализируется обычным "старым дедовским" способом, через
присваивание ему значения в теле конструктора, то для него сначала вызывается
конструктор по умолчанию, а потом оператор присваивания.
Если же инициализировать поле класса с помощью списка инициализации, то оно
будет сконструировано в один присест, через соответствующий конструктор.
Обычно это конструктор копирования или другой конструктор с аргументами.
То есть, получается в итоге одна операция вместо двух.
Как бы проверить-то? Не так оно просто. В конструктор по умолчанию (даже авторского типа) не вставишь диагностическую надпись "Вызван конструктор по умолчанию". Ибо тогда он уже не будет конструктором по умолчанию... Извините.

То есть приходится верить на слово, что при инициализации поля дедовским способом будет вызван конструктор по умолчанию. Ну, пусть так.
Убежденный
Системный программист
 Аватар для Убежденный
14197 / 6212 / 985
Регистрация: 02.05.2013
Сообщений: 10,353
Завершенные тесты: 1
19.01.2014, 16:42     Вылет программы с классом своего стека #14
Цитата Сообщение от kravam Посмотреть сообщение
Как бы проверить-то? Не так оно просто. В конструктор по умолчанию (даже авторского типа) не вставишь диагностическую надпись "Вызван конструктор по умолчанию". Ибо тогда он уже не будет конструктором по умолчанию.
"Конструктор по умолчанию" - здесь я подразумевал конструктор без аргументов,
так будет правильнее. Пример:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
#include <iostream>
 
 
 
using namespace std;
 
 
 
struct member
{
    member()
    {
        cout << "X" << endl;
    }
    
    member(member const &)
    {
        cout << "Y" << endl;
    }
    
    member &operator =(member const &)
    {
        cout << "Z" << endl;
        return (*this);
    }
};
 
 
 
struct container
{
    container(member const &Member)
    {
        m_Member = Member;
    }
    
    member m_Member;
};
 
 
 
int main()
{
    member Member;
    container Con(Member);
    return 0;
}
Вывод:
> X
> X
> Z
Если переписать конструктор container так:
C++
1
container(member const &Member) : m_Member(Member) {}
То получим другой вывод:
> X
> Y
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
19.01.2014, 20:56     Вылет программы с классом своего стека
Еще ссылки по теме:

Вылет программы для вычисления СЛАУ методом Жордана-Гаусса при исполнении C++
Вылет программы на деструкторе C++
Вылет программы при удалении динамического массива C++

Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
kravam
быдлокодер
 Аватар для kravam
1512 / 872 / 44
Регистрация: 04.06.2008
Сообщений: 5,271
19.01.2014, 20:56     Вылет программы с классом своего стека #15
Цитата Сообщение от Убежденный Посмотреть сообщение
Если же инициализировать поле класса с помощью списка инициализации, то оно
будет сконструировано в один присест, через соответствующий конструктор.
Был введён в заблуждение соответствующим конструктором, типа где его брать-то? А надо написать самому и всё будет ОК
Yandex
Объявления
19.01.2014, 20:56     Вылет программы с классом своего стека
Ответ Создать тему
Опции темы

Текущее время: 20:22. Часовой пояс GMT +3.
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2016, vBulletin Solutions, Inc.
Рейтинг@Mail.ru