Должны ли указатели-члены всегда использовать new при инициализации?

В этот вопрос, Я получаю странную ошибку сегментации в методе, который вызывает конструктор, но, видимо, больше нигде (даже в CodeBreaker::testVectorOfElements звонил из main() чье определение выглядит так:

void CodeBreaker::testVectorOfElements(int size)
{
// try to do what you did in makeNumericCodes with the vector
while (this->numericCodes.size() < size)
{
this->numericCodes.push_back(this->Z[0]);
}
}

CodeBreaker имеет частный std::vector<IntegerRing::Element> numericCodes,

Источник этой проблемы, кажется, с моей декларацией IntegerRing, который является IntegerGroup, Код MCVE для обоих классов можно найти ниже:

IntegerGroup.h

#ifndef INTEGERGROUP_H
#define INTEGERGROUP_H

#include "Array.h"#include <vector>   // for some reason, this didn't work.

#include <iostream>

// This group is the integers mod n
// multiplication in integer group is simply integer addition modulo n
class IntegerGroup
{
public:
IntegerGroup();
IntegerGroup(int);
class GroupElement
{
protected:
int m;
IntegerGroup* group;
public:
GroupElement();
GroupElement(int);
GroupElement(int, IntegerGroup*);
~GroupElement();
};
int size() const;
protected:
int n;
Array<GroupElement> elements;
void createNewElement(int);
};

#endif

IntegerGroup.cpp

#include "IntegerGroup.h"
#include <new>
#include <iostream>

IntegerGroup::IntegerGroup()
{

}

IntegerGroup::IntegerGroup(int n)
: n(n), elements(Array<IntegerGroup::GroupElement>(n))
//elements(std::vector<IntegerGroup::GroupElement>(n))
{
//this is to have integers in [0,n-1]
for (int j = 0; j < n; j++)
{
this->createNewElement(j);
}
}

void IntegerGroup::createNewElement(int m)
{
// create new GroupElement
GroupElement newElement(m, this);
// store it at index m in elements
this->elements[m] = newElement;
}

IntegerGroup::GroupElement::GroupElement()
: group(0)
{

}

IntegerGroup::GroupElement::GroupElement(int x)
: m(x), group(0)
{

}

IntegerGroup::GroupElement::GroupElement(int m, IntegerGroup * g)
: group(g)
{
// this->m must be in [0, g->size() - 1], if g not null
if (g)
{
this->m = m % g->size();
if (this->m < 0) this->m = g->size() + this->m;
}
else
{
this->m = m;
}
}

IntegerGroup::GroupElement::~GroupElement()
{
if (this->group)
{
this->group = 0;
}
}

int IntegerGroup::size() const { return this->n; }

IntegerRing.h

#ifndef INTEGERRING_H
#define INTEGERRING_H

#include "IntegerGroup.h"class IntegerRing : public IntegerGroup
{
public:
IntegerRing();
IntegerRing(int);
IntegerRing(const IntegerGroup&);
class Element : public IntegerGroup::GroupElement::GroupElement
{
public:
Element();
Element(int, IntegerGroup*);
//~Element();
operator IntegerGroup::GroupElement() { return IntegerGroup::GroupElement(); }
Element(const IntegerGroup::GroupElement&);
};
};

#endif

IntegerRing.cpp

#include "IntegerRing.h"#include "IntegerGroup.h"

#include <iostream>

IntegerRing::Element::Element()
: IntegerGroup::GroupElement()
{

}

IntegerRing::IntegerRing(int n)
: IntegerGroup::IntegerGroup(n)
{

}

IntegerRing::Element::Element(int m, IntegerGroup * g)
: IntegerGroup::GroupElement(m, g)
{

}

IntegerRing::Element::Element(const IntegerGroup::GroupElement& el)
: IntegerGroup::GroupElement(el)
{

}

CodeBreaker.h

#ifndef CODEBREAKER_H
#define CODEBREAKER_H

#include <string>
#include <map>
#include <utility>
#include <vector>

#include "IntegerRing.h"#include "PunctuationOccurrenceList.h"
class CodeBreaker
{
public:
CodeBreaker();
CodeBreaker(std::string&, bool);
void testVectorOfElements(int);
private:
PunctuationOccurrenceList punctuation;
IntegerRing Z;
void initCharMap();
void makeNumericCodes();
int getNumericCodeFor(char) const;
std::map<char, int> charFrequencyMap;
std::vector<IntegerRing::Element> numericCodes;
std::string ciphertext, plaintext;
std::string cipherFilename;
};

#endif

CodeBreaker.cpp

#include "CodeBreaker.h"
#include <iostream>
#include <fstream>
#include <algorithm>

CodeBreaker::CodeBreaker()
: Z(IntegerRing::IntegerRing(26)),
punctuation(PunctuationOccurrenceList::PunctuationOccurrenceList())
{
// initialize charFrequencyMap
this->initCharMap();
}

CodeBreaker::CodeBreaker(std::string& str, bool readFromFile)
: Z(IntegerRing::IntegerRing(26))
{
// if reading from file
if (readFromFile)
{
// str is filename to read from
// open file specified by str
std::ifstream input(str.c_str());
std::string line;
// read contents to ciphertext
while (std::getline(input, line))
{
this->ciphertext += line + "\n";
}
// close file
input.close();
}
// otherwise
else
{
// str is ciphertext itself
// write it to this->ciphertext
this->ciphertext = str;
}
// strip punctuation
this->punctuation = PunctuationOccurrenceList::PunctuationOccurrenceList(this->ciphertext);
// log numeric codes ('A' => 0, 'B' => 1, ... , 'Z' => 25)
this->makeNumericCodes();
}

void CodeBreaker::makeNumericCodes()
{
std::cout << "this->ciphertext.size() == " << this->ciphertext.size() << std::endl;
std::cout << "this->numericCodes.capacity() == " << this->numericCodes.capacity() << std::endl;
std::cout << "this->numericCodes.max_size() == " << this->numericCodes.max_size() << std::endl;
// if there isn't as many numeric codes as there are characters in ciphertext
while (this->numericCodes.size() < this->ciphertext.size())
{
std::cout << "Pushing dummy Element to numericCodes...\n";
this->numericCodes.push_back(this->Z[0]);
}
// for every character in ciphertext
for (int j = 0; j < this->ciphertext.size(); j++)
{
// if character's numerical code is not logged in numericCodes
int numericCode = this->getNumericCodeFor(ciphertext[j]);
if (numericCode != this->numericCodes[j].val())
// log it
this->numericCodes[j] = (IntegerRing::Element)this->Z[numericCode];

}
// while there are more numericCodes than characters in ciphertexts
while (this->numericCodes.size() > this->ciphertext.size())
// remove last character
this->numericCodes.pop_back();
}

void CodeBreaker::testVectorOfElements(int size)
{
// try to do what you did in makeNumericCodes with the vector
while (this->numericCodes.size() < size)
{
this->numericCodes.push_back(this->Z[0]);
}
}

int CodeBreaker::getNumericCodeFor(char c) const
{
// if character is in ['A', 'Z']
if ((c >= 'A') && (c <= 'Z'))
// return its int value minus 'A'
return (int)(c - 'A');
// otherwise, if it is in ['a', 'z']
if ((c >= 'a') && (c <= 'z'))
// return its int value minus 'a'
return (int)(c - 'a');
std::cout << "invalid character: " << c << std::endl;
return -1;
}

void CodeBreaker::initCharMap()
{
for (char c = 'A'; c <= 'Z'; c++)
{
this->charFrequencyMap[c] = 0;
}
}

main.cpp

#include <iostream>
#include <string>

#include "CodeBreaker.h"//#include "IntegerRing.h"

using namespace std;

int main()
{
bool testInClass = true;
if (testInClass)
{
string str = "I'm plaintext, but deal with me anyways, because this is mock code.";
CodeBreaker c(str, false);
/*CodeBreaker d;
d.testVectorOfElements(64);*/
}
else
{
vector<IntegerRing::Element> a;
IntegerRing Z(26);
cout << "a.capacity == " << a.capacity() << endl;
while (a.size() < 2400)
{
a.push_back(Z[0]);
}
cout << "a.size() == " << a.size() << endl;
for (int j = 0; j < 26; j++)
{
cout << a[j] << " ";
}
cout << endl;
}
return 0;
}

Array это просто сделай самvector что я должен был написать несколько лет назад для класса структур данных. Я использовал это вместо vector именно для проблемы, которую я имею здесь. (Проблемно-ception?)

Весь код доступен Вот, и вопрос в том, должен ли я использовать new когда я назначаю эти указатели? когда IntegerRing создается, он пытается создать IntegerRing::Elements, на который он передает указатель на себя (из-за необходимости: математическое определение кольца требует, чтобы оно было снабжено сложением и умножением, а элементы этой математической структуры используют этот оператор).

1

Решение

Задача ещё не решена.

Другие решения

Других решений пока нет …