I'm looking into C++11 move constructors but something doesn't work. In fact the issue is even before I started writing such a constructor. Here's a code snipped:
#include <iostream>
#include <string>
#include <sstream>
class Object {
static std::ostream& log(Object &obj) {
std::cout << "Object::id = " << obj.mId << "::";
return std::cout;
}
unsigned mId = 0;
std::string *mText = nullptr;
unsigned nextUniqueId() const {
static unsigned id = 0;
return ++id;
}
const std::string textInfo() const {
std::ostringstream oss;
oss << "mText # " << &mText;
if (mText) oss << " = " << *mText;
return oss.str();
}
public:
Object() = delete;
Object& operator= (const Object&) = delete;
explicit Object(const std::string& str) : mId(this->nextUniqueId()), mText(new std::string(str)) {
Object::log(*this) << "constructor::one-argument\n";
}
Object(const Object& obj) : mId(this->nextUniqueId()), mText(new std::string(*obj.mText)) {
Object::log(*this) << "constructor::copy\n";
}
virtual ~Object() {
Object::log(*this) << "destructor::" << this->textInfo() << "\n";
if (mText) {
delete mText;
mText = nullptr;
}
}
};
static Object get_object() {
return Object("random text");
}
int main(int argc, char **argv) {
Object a("first object"); // OK
/*
* Expected behaviour: inside get_object() function new Object is created which is then copied into
* variable b. So that new ID should be given.
*/
Object b = get_object(); // What the hell?! Not what expected! Why?
std::cout << std::endl;
return 0;
}
The expected output is similiar to this:
Object::id = 1::constructor::one-argument
Object::id = 2::constructor::one-argument
Object::id = 2::destructor::mText # 0x7fff32c25f70 = random text
Object::id = 3::constructor::copy
Object::id = 3::destructor::mText # <DIFFERENT THAN IN ID=2> = random text
Object::id = 1::destructor::mText # 0x7fff32c25f90 = first object
I get this instead:
Object::id = 1::constructor::one-argument
Object::id = 2::constructor::one-argument
Object::id = 2::destructor::mText # 0x7fff32c25f70 = random text
Object::id = 1::destructor::mText # 0x7fff32c25f90 = first object
which looks like variable b is created on spot (something like inline maybe?). Frankly speaking I don't know what's going on, can anyone explain?
The compiler optimized out the copy/move is all...
That is called return value optimization or RVO. The compiler opted to create the temporary returned by get_object() directly in the memory location of b in main. It is sanctioned by the standard and a very common optimization.
The compiler is allowed to apply "return value optimization" RVO and that's why the copy is optimized out. Note that the standard allows this despite the side effects related to the output message
Related
class Person
{
public:
string fname;
string lname;
string occupation;
string gender;
int age;
};
int main()
{
Person bc;
bc.fname = "Bevelry";
bc.lname = "Crusher";
bc.gender = "female";
bc.occupation = "Doctor, USS 1701-D";
bc.age = 40;
cout << bc.all << "\n"; //Something like this?
}
Is it possible for me to print every variable of an object without specifying them by myself? And is it possible for me to make a select list of variables, something like an array of variables, and then print them?
EDIT: i accidently put the cout in the class, fixed now
Is it possible for me to print every variable of an object without specifying them by myself?
No.
And is it possible for me to make a select list of variables, something like an array of variables, and then print them?
Not automatically, but you could create a collection of std::anys and add some decoding for it yourself.
Example:
#include <any>
#include <functional>
#include <iostream>
#include <iterator>
#include <string>
#include <vector>
// decode and print one std::any
void decode_one(std::ostream& os, const std::any& a) {
if(auto s = std::any_cast<std::reference_wrapper<std::string>>(&a)) os << s->get();
else if(auto i = std::any_cast<std::reference_wrapper<int>>(&a)) os << *i;
else if(auto d = std::any_cast<std::reference_wrapper<double>>(&a)) os << *d;
// add more types to decode here
else os << "<unknown type>";
}
// a custom ostream operator to decode a vector of anys:
std::ostream& operator<<(std::ostream& os, const std::vector<std::any>& va) {
auto begin = va.begin();
auto end = va.end();
if(begin != end) {
decode_one(os, *begin);
for(std::advance(begin, 1); begin != end; std::advance(begin, 1)) {
os << ',';
decode_one(os, *begin);
}
}
return os;
}
int main() {
int a = 10;
std::string b = "Hello world";
double c = 3.14159;
std::vector<std::any> va{
std::ref(a),
std::ref(b),
std::ref(c)
};
c *= 2.; // just to show that the vector holds a reference
std::cout << va << '\n'; // print the variables in the vector
}
Output:
10,Hello world,6.28318
It's not possible. In C++ there isn't anything that does what you want.
At one side one can easily say that this is not possible in C++.
However, at the other side, one can add that this situation happens quite often when people are making object oriented computer programs, and in Java there is the toString() method for this. So, you might actually write your own toString() method (based on the way it is done in Java), and work with this.
Good luck
I have a class that defines object.name as "Ben" and object.favNum as 25.
I also have an array (names) to store 5 objects of this class.
Before I output the attributes of the objects in the array, I change the value of names[0].name to "Jim" and names[0].favNum to 40, using pointer notation.
Here is my code:
#include<iostream>
class Person {
public:
std::string name = "Ben";
int favNum = 25;
};
int main()
{
Person names[5];
Person *ptr = &names[0];
// Changing Values
(ptr + 0)->name = "Jim";
(ptr + 0)->favNum = 40;
for (int i = 0; i < 5; i++)
{
std::cout << (std::string) (ptr + i)->name << std::endl;
std::cout << (int) (ptr + i)->favNum << std::endl << std::endl;
}
system("pause>0");
}
Output:
Jim
40
Ben
25
Ben
25
Ben
25
Ben
25
Where I have the "Changing Values" comment, I want to replace those 2 lines with a function.
The function will be able to change the values as I am doing with the 2 lines.
This is where I am having a problem.
I'm struggling with figuring out what type to declare the function as, how to pass the pointer in, how to receive the pointer, and how to change the values of the objects in the array in the function.
I would recommend against the use of pointers, unless you really need pointers.
// use references instead
void change(Person &person) {
person.name = "Jim";
person.favNum = 40;
};
int main()
{
Person names[5];
change(names[0]);
// ...
}
The appropriate way to write such a function would be using references. A reference is similar to a pointer, but can never be nullptr. In your case you don't need nullability, you just need to edit a Person without copying it.
You probably want change() to be parametric though:
// use references instead
void change(Person &person, std::string name, int favNum) {
person.name = std::move(name);
person.favNum = favNum;
}
But now you are assigning all members of Person using this function, which makes it pointless. It would be simpler if you assigned Person. Why not use a struct and aggregate initialization:
struct Person {
std::string name = "Ben";
int favNum = 25;
};
int main()
{
Person names[5];
names[0] = {"Jim", 40};
// ...
}
On a side note, what you are doing here is unnecessary complicated:
(ptr + 0)->name = "Jim";
// this is equivalent to
ptr[0].name = "Jim";
// this is equivalent to
ptr->name = "Jim";
This is how your code should look in "real" c++ (the setting of the values will be done in the constructor function or using the setNameAndFavNum() function):
#include <array>
#include <iostream>
struct Person {
public:
Person(const std::string& name_ = "Ben", int favNum_ = 25) : name(name_), favNum(favNum_) {};
void setNameAndFavNum(const std::string& name_, int favNum_) {
name = name_;
favNum = favNum_;
};
std::string name;
int favNum;
};
int main() {
std::array<Person, 5> names;
// Changing Values
names[0].setNameAndFavNum("Jim", 40);
// Alternatively you can use the constructor and implicit copy constructor
// names[0] = {"Jim", 40};
for (int i = 0; i < names.size(); i++) {
std::cout << names[i].name << std::endl;
std::cout << names[i].favNum << std::endl << std::endl;
}
}
You shouldn't mess around with pointers and raw values when writing c++ code.
Currently working on Object Oriented Programming in c++ and having problems with an instance showing nothing changed from a method I've created.
The whole code is based off of this object I've created from a header file.
#ifndef DEQUE_H_
#define DEQUE_H_
#include <iostream>
const int CAPACITY = 5;
const int DEFAULT = -1;
class Deque
{
public:
Deque();
int get_size() const;
bool is_empty() const;
bool is_full() const;
int operator[](int i) const;
static Deque insert_tail(int);
private:
int size_;
static int array_[CAPACITY];
};
std::ostream & operator<<(std::ostream &, const Deque &);
#endif
One of the problems I'm having is the insert_tail method that doesn't show any changes to my static array.
In the cpp file itself.. these are the function declarations.
#
include <iostream>
#include "Deque.h"
Deque::Deque()
:size_(0)
{
}
int Deque::array_[5] = {};
int Deque::get_size() const
{
return size_;
}
bool Deque::is_full() const
{
if (size_ == 5) return 1;
else return 0;
}
bool Deque::is_empty() const
{
if (size_!= 5) return 1;
else return 0;
}
int Deque::operator[](int i) const
{
int something = array_[i];
return something;
}
Deque Deque::insert_tail(int x)
{
Deque d;
d.size_ += 1;
int size = d.size_;
d.array_[size - 1] = x;
return d;
}
std::ostream & operator<<(std::ostream & cout, const Deque & dq)
{
cout << dq.get_size() << " [ ";
for (int i = 0; i < dq.get_size(); ++i)
{
cout << dq[i] << " ";
}
cout << "]";
return cout;
}
The operator works just fine. The bools work just fine and the remove_head and remove_tail thing I'll do once I figure out insert tail. Right now, it's not making any chances to the very object I've created inside the main.
#include <iostream>
#include "Deque.h"
void print(const Deque & deque)
{
static int i = 1;
std::cout << i << ". " << deque << ", empty: " << deque.is_empty()
<< ", full: " << deque.is_full();
i++;
}
void test_insert_tail(Deque & deque, int x)
{
deque.insert_tail(x);
print(deque); std::cout << "\n";
}
int main()
{
Deque deque;
print(deque);
std::cout << "\n";
test_insert_tail(deque, 2);
return 0;
}
The output should look like this,
1. 1 [ 2 ], empty: 0, full: 0
but looks like this
1. 0 [], empty: 1, full: 0
What's going on inside my static method for handling all the private attributes that I'm missing on? What did I do wrong exactly?
The problem with your code is the misuse of the static word. In fact, static means that is not associated with an instance of the object: this means that the content of the static member (the array_ variable in this case) is shared between every instance you will create.
That's the same for the insert_tail method, that can be used even if you don't create an instance. Now, let's try to understand what you've written in this method:
Deque d;
d.size_ += 1;
int size = d.size_;
d.array_[size - 1] = x;
return d;
In the first line, you created a new Deque object. That's the first mistake, cause you're not modifying the actual Deque. Then you add the operations, and in the end, you return the created Deque. However, this object is not saved anywhere, because when you call deque.insert_tail() you aren't assigning the returned value anywhere.
Let's try and get this a little bit more concrete.
Since what you're doing is creating a data structure, you won't need any static member. This because everything needs to be saved inside the data structure.
Then, inside the insert_tail you'll need to remove the object you created inside. It'll look something like this:
size_ += 1;
int size = size_;
array_[size - 1] = x;
With those two modifications the code will probably work as expected, however, I suggest you focus on improving the appearance of your code. Using the underscore character at the end of the variable name is a little bit confusing. In C the only scenario you can use it inside the name int foo_bar for normal variables, and at the beginning int _foo for reserved variables.
I come from python world, and as a weekend project I decided to write a simple UDP server in c++. I have a question regarding correct way of discovering the type of incoming request. My approach is to have a class for every possible type of request. Upon packet arrival I have to unpack it's OPID (operation id) and instantiate correct class. To do that I have to bind OPIDs with the classes, and the only way I'm familiar of doing this in c++ involves huge switch:case block. Doing this doesn't really feels right for me, also If I understand UncleBob correctly, this goes against few OOP practices. As code describes the best one's intentions, here's python equivalent of what I'm trying to do with c++.
class BaseOperation:
OPID = 0
def process(packet_data):
raise NotImplementedError("blah blah")
class FooOperation(BaseOperation):
OPID = 1
def process(packet_data):
print("Foo on the packet!")
class BarOperation(BaseOperation):
OPID = 2
def process(packet_data):
print("Bar on the packet!")
opid_mappings = {
FooOperation.OPID: FooOperation,
BarOperation.OPID: BarOperation
}
Somewhere in code handling the incoming packet
def handle_connection(packet):
try:
operation = opid_mappings[get_opid(packet)]()
except KeyError:
print("Unknown OPID")
return
operation.process(get_data(packet))
Really quick hack of object-based solution. This might not be the right way to go in our wonderful new C++11 world of std::function.
If the children of BaseOperation need to store state, go objects!
#include <iostream>
#include <map>
class BaseOperation
{
protected:
int OPID;
public:
virtual ~BaseOperation()
{
}
virtual int operator()() = 0;
};
class FooOperation:public BaseOperation
{
public:
static constexpr int OPID = 1;
FooOperation()
{
}
int operator()()
{
// do parsing
return OPID; // just for convenience so we can tell who was called
}
};
constexpr int FooOperation::OPID; // allocate storage for static
class BarOperation:public BaseOperation
{
public:
static constexpr int OPID = 2;
BarOperation()
{
}
int operator()()
{
// do parsing
return OPID; // just for convenience so we can tell who was called
}
};
constexpr int BarOperation::OPID; // allocate storage for static
std::map<int, BaseOperation*> opid_mappings{
{FooOperation::OPID, new FooOperation()},
{BarOperation::OPID, new BarOperation()}
};
int main()
{
std::cout << "calling OPID 1:" << (*opid_mappings[1])() << std::endl;
std::cout << "calling OPID 2:" << (*opid_mappings[2])() << std::endl;
for (std::pair<int, BaseOperation*> todel: opid_mappings)
{
delete todel.second;
}
return 0;
}
This also ignores the fact that there is probably no need for the map. If the OPIDs are sequential, a good ol' dumb array solves the problem. I like the map because it won't screw up if someone moves a parser handler or inserts one into the middle of the list.
Regardless, this has a bunch of memory management problems, such as the need for the for loop deleting the parser objects at the bottom of main. This could be solved with std::unique_ptr, but this is probably a rabbit hole we don't need to go down.
Odds are really good that the parser doesn't have any state and we can just use a map of OPIDs and std::function.
#include <iostream>
#include <map>
#include <functional>
static constexpr int FooOPID = 1;
int fooOperation()
{
// do parsing
return FooOPID;
}
static constexpr int BarOPID = 2;
int BarOperation()
{
// do parsing
return BarOPID;
}
std::map<int, std::function<int()>> opid_mappings {
{FooOPID, fooOperation},
{BarOPID, BarOperation}
};
int main()
{
std::cout << "calling OPID 1:" << opid_mappings[1]() << std::endl;
std::cout << "calling OPID 2:" << opid_mappings[2]() << std::endl;
return 0;
}
And because the parser's are kind of useless if you aren't passing anything in, one last tweak:
#include <iostream>
#include <map>
#include <functional>
struct Packet
{
//whatever you need here. Probably a buffer reference and a length
};
static constexpr int FooOPID = 1;
int fooOperation(Packet & packet)
{
// do parsing
return FooOPID;
}
static constexpr int BarOPID = 2;
int BarOperation(Packet & packet)
{
// do parsing
return BarOPID;
}
std::map<int, std::function<int(Packet &)>> opid_mappings {
{FooOPID, fooOperation},
{BarOPID, BarOperation}
};
int main()
{
Packet packet;
std::cout << "calling OPID 1:" << opid_mappings[1](packet) << std::endl;
std::cout << "calling OPID 2:" << opid_mappings[2](packet) << std::endl;
return 0;
}
I am trying to write a logger class for my C++ calculator, but I'm experiencing a problem while trying to push a string into a list.
I have tried researching this issue and have found some information on this, but nothing that seems to help with my problem. I am using a rather basic C++ compiler, with little debugging utilities and I've not used C++ in quite some time (even then it was only a small amount).
My code:
#ifndef _LOGGER_H_
#define _LOGGER_H_
#include <iostream>
#include <list>
#include <string>
using std::cout;
using std::cin;
using std::endl;
using std::list;
using std::string;
class Logger
{
private:
list<string> mEntries;
public:
Logger() {}
~Logger() {}
// Public Methods
void WriteEntry(const string& entry)
{
mEntries.push_back(entry);
}
void DisplayEntries()
{
cout << endl << "**********************" << endl
<< "* Logger Entries *" << endl
<< "**********************" << endl
<< endl;
for(list<string>::iterator it = mEntries.begin();
it != mEntries.end(); it++)
{
// *** BELOW LINE IS MARKED WITH THE ERROR ***
cout << *it << endl;
}
}
};
#endif
I am calling the WriteEntry method by simply passing in a string, like so:
mLogger->WriteEntry("Testing");
Any advice on this would be greatly appreciated.
* CODE ABOVE HAS BEEN ALTERED TO HOW IT IS NOW *
Now, the line:
cout << *it << endl;
causes the same error. I'm assuming this has something to do with how I am trying to get the string value from the iterator.
The code I am using to call it is in my main.cpp file:
#include <iostream>
#include <string>
#include <sstream>
#include "CommandParser.h"
#include "CommandManager.h"
#include "Exceptions.h"
#include "Logger.h"
using std::string;
using std::stringstream;
using std::cout;
using std::cin;
using std::endl;
#define MSG_QUIT 2384321
#define SHOW_LOGGER true
void RegisterCommands(void);
void UnregisterCommands(void);
int ApplicationLoop(void);
void CheckForLoggingOutput(void);
void ShowDebugLog(void);
// Operations
double Operation_Add(double* params);
double Operation_Subtract(double* params);
double Operation_Multiply(double* params);
double Operation_Divide(double* params);
// Variable
CommandManager *mCommandManager;
CommandParser *mCommandParser;
Logger *mLogger;
int main(int argc, const char **argv)
{
mLogger->WriteEntry("Registering commands...\0");
// Make sure we register all commands first
RegisterCommands();
mLogger->WriteEntry("Command registration complete.\0");
// Check the input to see if we're using the program standalone,
// or not
if(argc == 0)
{
mLogger->WriteEntry("Starting application message pump...\0");
// Full version
int result;
do
{
result = ApplicationLoop();
} while(result != MSG_QUIT);
}
else
{
mLogger->WriteEntry("Starting standalone application...\0");
// Standalone - single use
// Join the args into a string
stringstream joinedStrings(argv[0]);
for(int i = 1; i < argc; i++)
{
joinedStrings << argv[i];
}
mLogger->WriteEntry("Parsing argument '" + joinedStrings.str() + "'...\0");
// Parse the string
mCommandParser->Parse(joinedStrings.str());
// Get the command names from the parser
list<string> commandNames = mCommandParser->GetCommandNames();
// Check that all of the commands have been registered
for(list<string>::iterator it = commandNames.begin();
it != commandNames.end(); it++)
{
mLogger->WriteEntry("Checking command '" + *it + "' is registered...\0");
if(!mCommandManager->IsCommandRegistered(*it))
{
// TODO: Throw exception
mLogger->WriteEntry("Command '" + *it + "' has not been registered.\0");
}
}
// Get each command from the parser and use it's values
// to invoke the relevant command from the manager
double results[commandNames.size()];
int currentResultIndex = 0;
for(list<string>::iterator name_iterator = commandNames.begin();
name_iterator != commandNames.end(); name_iterator++)
{
string paramString = mCommandParser->GetCommandValue(*name_iterator);
list<string> paramStringArray = StringHelper::Split(paramString, ' ');
double params[paramStringArray.size()];
int index = 0;
for(list<string>::iterator param_iterator = paramStringArray.begin();
param_iterator != paramStringArray.end(); param_iterator++)
{
// Parse the current string to a double value
params[index++] = atof(param_iterator->c_str());
}
mLogger->WriteEntry("Invoking command '" + *name_iterator + "'...\0");
results[currentResultIndex++] =
mCommandManager->InvokeCommand(*name_iterator, params);
}
// Output all results
for(int i = 0; i < commandNames.size(); i++)
{
cout << "Result[" << i << "]: " << results[i] << endl;
}
}
mLogger->WriteEntry("Unregistering commands...\0");
// Make sure we clear up our resources
UnregisterCommands();
mLogger->WriteEntry("Command unregistration complete.\0");
if(SHOW_LOGGER)
{
CheckForLoggingOutput();
}
system("PAUSE");
return 0;
}
void RegisterCommands()
{
mCommandManager = new CommandManager();
mCommandParser = new CommandParser();
mLogger = new Logger();
// Known commands
mCommandManager->RegisterCommand("add", &Operation_Add);
mCommandManager->RegisterCommand("sub", &Operation_Subtract);
mCommandManager->RegisterCommand("mul", &Operation_Multiply);
mCommandManager->RegisterCommand("div", &Operation_Divide);
}
void UnregisterCommands()
{
// Unregister each command
mCommandManager->UnregisterCommand("add");
mCommandManager->UnregisterCommand("sub");
mCommandManager->UnregisterCommand("mul");
mCommandManager->UnregisterCommand("div");
// Delete the logger pointer
delete mLogger;
// Delete the command manager pointer
delete mCommandManager;
// Delete the command parser pointer
delete mCommandParser;
}
int ApplicationLoop()
{
return MSG_QUIT;
}
void CheckForLoggingOutput()
{
char answer = 'n';
cout << endl << "Do you wish to view the debug log? [y/n]: ";
cin >> answer;
switch(answer)
{
case 'y':
ShowDebugLog();
break;
}
}
void ShowDebugLog()
{
mLogger->DisplayEntries();
}
// Operation Definitions
double Operation_Add(double* values)
{
double accumulator = 0.0;
// Iterate over all values and accumulate them
for(int i = 0; i < (sizeof values) - 1; i++)
{
accumulator += values[i];
}
// Return the result of the calculation
return accumulator;
}
double Operation_Subtract(double* values)
{
double accumulator = 0.0;
// Iterate over all values and negativel accumulate them
for(int i = 0; i < (sizeof values) - 1; i++)
{
accumulator -= values[i];
}
// Return the result of the calculation
return accumulator;
}
double Operation_Multiply(double* values)
{
double accumulator = 0.0;
for(int i = 0; i < (sizeof values) - 1; i++)
{
accumulator *= values[i];
}
// Return the value of the calculation
return accumulator;
}
double Operation_Divide(double* values)
{
double accumulator = 0.0;
for(int i = 0; i < (sizeof values) - 1; i++)
{
accumulator /= values[i];
}
// Return the result of the calculation
return accumulator;
}
Did you remember to call mLogger = new Logger at some point? Did you accidantally delete mLogger before writing to it?
Try running your program in valgrind to see whether it finds any memory errors.
After your edit, the solution seem clear:
Your first line in main() is :
mLogger->WriteEntry("Registering commands...\0");
Here mLogger is a pointer that has never been initialized. This is "undefined behaviour", meaning anything can appen, often bad things.
To fix this you can either make it a "normal" variable, not a pointer or create a Logger instance using new (either at the declaration or as the first line in main).
I suggest you to not use a pointer to be sure the logger is always there and is automatically destroyed.
By the way, it seems like you want to create every instance of objects on the heap using pointers. It's not recommanded if it's not necessary. You should use pointers ONLY if you want to explicitely state the creation (using new) and destruction (using delete) of the instance object. If you just need it in a specific scope, don't use a pointer. You might come from another language like Java or C# where all objects are referenced. If so, you should start learning C++ like a different language to avoid such kind of problem. You should learn about RAII and other C++ scpecific paradigm that you cannot learn in those languages. If you come from C you should too take it as a different language. That might help you avoid complex problems like the one you showed here. May I suggest you read some C++ pointer, references and RAII related questions on stackoverflow.
First, you don't need to create the std::list on the heap. You should just use it as a normal member of the class.
class Logger
{
private:
list<string> mEntries; // no need to use a pointer
public:
Logger() // initialization is automatic, no need to do anything
{
}
~Logger() // clearing and destruction is automatic too, no need to do anything
{
}
//...
};
Next, entryData don't exist in this code so I guess you wanted to use entry. If it's not a typo then you're not providing the definition of entryData that is certainly the source of your problem.
In fact I would have written your class that way instead:
class Logger
{
private:
list<string> mEntries;
public:
// no need for constructor and destructor, use the default ones
// Public Methods
void WriteEntry(const string& entry) // use a const reference to avoid unnecessary copy (even with optimization like NRVO)
{
mEntries.push_back( entry ); // here the list will create a node with a string inside, so this is exactly like calling the copy constructor
}
void DisplayEntries()
{
cout << endl << "**********************" << endl
<< "* Logger Entries *" << endl
<< "**********************" << endl
<< endl;
for(list<string>::iterator it = mEntries.begin();
it != mEntries.end(); ++it) // if you want to avoid unnecessary copies, use ++it instead of it++
{
cout << *it << endl;
}
}
};
What's certain is that your segfault is from usage outside of this class.
Is an instance of Logger being copied anywhere (either through a copy constructor or operator=)? Since you have mEntries as a pointer to a list, if you copy an instance of Logger, they will share the value of the pointer, and when one is destructed, it deletes the list. The original then has a dangling pointer. A quick check is to make the copy constructor and operator= private and not implemented:
private:
void operator=(const Logger &); // not implemented
Logger(const Logger &); // not implemented
When you recompile, the compiler will flag any copies of any Logger instances.
If you need to copy instances of Logger, the fix is to follow the Rule of 3:
http://en.wikipedia.org/wiki/Rule_of_three_%28C%2B%2B_programming%29
You can do this by eliminating the need for the destructor (by not using a pointer: list<string> mEntries), or by adding the needed code to the copy constructor and operator= to make a deep copy of the list.
You only need to do
list<string> entries;
entries.push_back();
You do not need to create a pointer to entries.
Nothing too obvious, though you typed
mEntries->push_back(string(entryData));
and I htink you meant entry instead of entryData. You also don't need the string conversion on that line, and your function should take entry by const reference.
However, none of these things would cause your program to segfault. What compiler are you using?
You're missing the copy constructor. If the Logger object is copied and the original deleted, you'll be dereferencing memory that was previously deleted.
A simplified example of the problem
Logger a;
{
Logger b;
a=b;
}
a.WriteEntry("Testing");
Add a copy constructor.
Logger(const Logger& item)
{
mEntries = new list<string>();
std::copy(item.mEntries->begin(), item.mEntries->end(), std::back_inserter(*mEntries));
}