Я создавал небольшой класс стека шаблонов для стороннего проекта, и он, похоже, работал правильно. Однако, когда я попробовал это со строками, это не сработало. У меня нет ошибок компиляции или предупреждений. Я просто не получаю выход. Я немного заржавел в C++, но я не ожидал, что меня заблокирует проблема, которая кажется такой простой.
Моя основная функция (для тестирования):
#include <iostream>
#include <fstream>
#include <string>
#include "myStack.h"
int main()
{
bool repeat = true;
int option = -1;
std::cout << "Option (1 - String | 2 - Integer) : ";
std::cin >> option;
std::cout << "\n";
switch (option)
{
case 1:
{
myStack<std::string> stringStack;
stringStack.push("!");
stringStack.push("there");
stringStack.push("Hello");
stringStack.show();
break;
}
case 2:
{
myStack<int> intStack;
intStack.push(3);
intStack.push(2);
intStack.push(1);
intStack.show();
break;
}
default:
break;
}
std::cout << "\n";
return 0;
}
Соответствующие части моего класса стека:
#pragma once
template <typename T>
class myStack
{
private:
T *elements;
size_t capacity;
public:
myStack();
T top();
size_t size();
void push(T pushed);
void pop();
bool isEmpty();
void show(std::ostream &out = std::cout);
};
template <typename T>
myStack<T>::myStack()
{
this->elements = NULL;
this->capacity = 0;
}
template <typename T>
void myStack<T>::push(T pushed)
{
this->elements = (T *)realloc(this->elements, (this->capacity + 1) * sizeof(T));
this->elements[this->capacity] = pushed;
this->capacity++;
}
template<typename T>
void myStack<T>::show(std::ostream &out)
{
for (int i = this->capacity - 1; i >= 0; i--)
{
out << this->elements[i] << std::endl;
}
}
Вы не можете хранить std::string
таким образом. Это не тривиально копируется.
GCC фактически выполняет дать соответствующее предупреждение здесь.
Выделение памяти для std::string
с помощью realloc()
(или malloc()
, или calloc()
) дает неопределенное поведение. Если вам необходимо динамически выделить std::string
или их набор, используйте оператор new
. Он работает с типами классов C++, у которых есть конструкторы, включая std::string
.
@chris, значит, проблема в моем Makefile, верно?
О, хорошо! Я привык к malloc() и realloc() и просто ожидал, что они будут работать и здесь. Спасибо всем за помощь!
Вы можете рассмотреть специализацию шаблона для типа std::string
@PedroAlves, похоже. Регулировки CXXFLAGS
должно быть достаточно.
Использование
this->elements = (T *)realloc(this->elements, (this->capacity + 1) * sizeof(T));
this->elements[this->capacity] = pushed;
управлять массивом std::string
s неправильно. Использование realloc
для выделения памяти допустимо. Однако он не инициализирует объект должным образом. Вторая строка является причиной неопределенного поведения, поскольку объект не был правильно инициализирован.
Если вам разрешено использовать std::vector
, используйте его.
template <typename T>
class myStack
{
private:
std::vector<T> elements;
...
};
Тогда использование capacity
можно заменить на elements.size()
.
push
можно упростить до:
template <typename T>
void myStack<T>::push(T pushed)
{
this->elements.push_back(pushed);
}
Вам также придется обновить show()
соответственно.
Кстати, вы, кажется, пропускаете предупреждения при фактической компиляции исходных файлов. Предупреждения присутствуют только для связывания.