Classic List of object in C++ using pointers [closed] - c++

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I'd like to make one directional list of objects in C++. I've got 3 classes: BasicMiachine,Desktop,Laptop. Two last classses extends BasicMachine. What I want to do is make a list of object (Desktop,Laptop) using only one list. In Basic Class which is abstract class (because I have declare one method as virtual) I have a field which is a pointer to next object is a BasicClass type. Below is my code:
int main () {
BasicClass* headList= NULL;
BasicClass* iterator = NULL;
while(....)
{
switch(.....){
case 1:
addNewComputer(headList,iterator,numberOfObjects);
break;
}
}
void static addNewComputer(BasicClass* headList, BasicClass* iterator,short numberOfObjects)
{
short choice;
cout<<"What is your machine?"<<endl<<"1) Desktop or2) Laptop"<<endl;
cout<<"Your choice: "; cin>>choice;
if(choice== 1)
{
//Add some data to variables// ....//
if(numberOfObjects == 0)
{
headList = new Desktop(wysokosc,dlugosc,szerokosc, taktowanieProcesora, numerIdentyfikacyjny, typProcesora, nazwaWSieci,ID);
iterator= headList ;
iterator->nextObject = NULL;
}
else
{
BasicClass* tmpIterator= NULL;
tmpIterator= headList ;
tmpIterator->nextObject = new Desktop(wysokosc,dlugosc,szerokosc, taktowanieProcesora, numerIdentyfikacyjny, typProcesora, nazwaWSieci,ID);
tmpIterator= pomocniczyWskaznik -> nextObject;
tmpIterator->nextObject = NULL;
}
}
else if(choice == 2)
{
//It is the same as above but I add here a La
}
};
After I add one and second computer I got an error like: "Access violation writing location 0x00000050." Is it a problem with pointers? I use BasicClass type pointers to hold both objects (Desktop, Laptop).

You make the classic mistake of passing pointers by value instead of by reference.
Change addNewComputer to e.g.
void static addNewComputer(BasicClass*& headList, BasicClass*& iterator,short numberOfObjects)
and things should work better.

I suggest you to take a look to standard containers. Anyway, the problem is that your are passing pointers by value, so when you call "new" the pointer inside addNewComputer() points to a new memory direction and when the function returns, headList and iterator are null (notice the memory leak issue). To solve your problem, you need to pass headList and iterator by reference i.e.
void static addNewComputer(BasicClass*& headList, BasicClass*& iterator,short numberOfObjects)
Hope this help.

Related

c++ attempting to reference a deleted function in non existing constructor (using rapidJson) [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 3 years ago.
Improve this question
I'm currently getting this error:
'User::User(const User&)': attempting to reference a deleted function
The program passes a string value of an object into the class.
User Constructor:
User::User(string s){
int size = s.length() + 1;
char* cstr = new char[size];
strcpy_s(cstr, size, s.c_str());
user.Parse(cstr);
}
Main Loop:
int main(){
//json equals something similar to this: "{\"body:{[{"user":1},{"user":1},{"user":1}]}\"}";
const char * json;
Document d;
d.Parse(json);
if (d.HasMember("body")) {
if (d["body"].IsArray()) {
for (SizeType i = 0; i < d["body"].Size(); i++) {
string json = getJsonString(d["body"][i]);
User u = User(json); \\this is where the error point to
this->users.push_back(u);
}
}
}
}
getJsonString function:
string getJsonString(Value& value) {
StringBuffer buffer;
buffer.Clear();
Writer<StringBuffer> writer(buffer);
value.Accept(writer);
return string(buffer.GetString());
}
I search for a lot of explanation on this error but nothing seems to make sense to me. I think it has something to do with the vector array however it doesn't make sense to me as I'm not using a pointer or reference for any of the user value. It seems to point to the constructor however no pointer or reference is being passed through. I through by returning the string of the json, I wasn't using a pointer but maybe I actually am? I would be grateful for any explanation to what I am doing wrong.
User is not copyable; this means that:
User::User(const User&) (copy constructor) is private
or deleted (= delete;)
or deleted implicitly (e.g. class has non-copyable members, or inherits from a non-copyable class). Thank you Yksisarvinen for the comment
This means you are not allowed to create a new User from another one.
Then, if you want to store User objects in a vector (as you are "apparently" trying to do in your post, I say "apparently" because the posted code does not compile, I dunno who is this) you cannot store them by value, as the vector contained needs an accessible copy constructor.
See std::vector:
T must meet the requirements of CopyAssignable and CopyConstructible.
However, you can store them as pointers:
std::vector<std::shared_ptr<User>> users;
users.push_back( std::shared_ptr<User>( new User( json ) );

Should I check if "std::string.c_str" is NULL? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am writing code C++ code in Xcode. At an instance I'm making sure that all fields are valid.
SomeClass *myclass = new SomeClass();
std::string myString;
if ( (myClass) && (myString.c_str)) {
return true;
} else {
return false;
}
Should i be checking for testString.c_str? Does it makes sense?
The default behavior of the new() operator is to either return the new object, or throw an exception if memory allocation failed. So, you don't need to check if myClass is NULL, unless you set the flags to change the behavior or implemented your own new() operator for your class.
Also, the extra brackets around myClass are not necessary. A better way to express what you want to check would be
if ((myClass != nullptr) &&
Then, you are currently testing if the address of the method c_str() in the std::string class is not NULL. Not want you want to do, I guess.
First, you would need to write myString.c_str(). Then, this method never returns a NULL pointer, what it can return is an empty C string. But this is better tested with std::string::empty(), so your check would look like this:
if (myString.empty()) {
return false;
} else {
return true;
}
which can of course be shortened into
return !myString.empty();
Finally: If you have this code in a function/method: Who deletes your new SomeClass object?

A convenient way to track memory allocated in a data loader? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 years ago.
Improve this question
In C++, we have to allocate/deallocate memory manually. In my loader function, this becomes a knotty problem. It loads data from a bunch of files containing different formats of data. And loading one file means doing a lot allocation in different places. The failure of one loading cause a total failure, which means I have to rollback all the allocation & initializition before. But the current design, using a lot of singletons, globals etc. doesn't provides a convenient way to rollback. I need suggestions or code samples to follow. Please help.
I guess build my own allocator is a good solution. But it doesn't works for foreign libraries used in my project who use their own allocators.
Please, don't say using smart pointers. It really means making my project more complicated.
So, some code is provided here. My project is a small interpreter. The language it interprets is XML. A complete program consists of several XML files, describing different data the program is using.
extern std::map<std::string, Sub *> g_subMap;
// ...
// load every `subroutines' defined in XML
// so what should I do if one of them fails to load?
XMLElement *pRootElem = doc.RootElement();
for (XMLElement *pChild1 = pRootElem->FirstChildElement(); pChild1; pChild1 = pChild1->NextSiblingElement()) {
if (stricmp(pChild1->Value(), "sub") == 0) {
const char *name = pChild1->Attribute("name");
Sub *pSub = new Sub();
bool success = pSub->Load(pChild1);
// ?
g_subMap[name] = pSub;
}
}
From the code you shared, here's a simple update.
Use a temp map to handle the loading. The destructor of subs will release the reference when it goes out of scope. If it hasn't been copied over to g_subMap, as in the success case, then the temporary loaded "Sub" objects are deleted for you.
map<string, shared_ptr<Sub>> subs;
bool success = true;
for (XMLElement *pChild1 = pRootElem->FirstChildElement(); pChild1; pChild1 = pChild1->NextSiblingElement())
{
if (stricmp(pChild1->Value(), "sub") == 0)
{
string name = pChild1->Attribute("name");
shared_ptr<Sub> spSub = shared_ptr<Sub>(new Sub());
subs[name] = spSub;
success = spSub->Load(pChild1);
if (success == false)
{
break;
}
}
}
if (success)
{
// migrate our temp map of "subs" into g_subMap, which has
// also been converted to be a map of shared_ptr<Sub>
for (auto itor = subs.begin(); itor != subs.end(); itor++)
{
g_subMap[itor->first] = itor->second; // shared_ptr reference count gets incremented on assignment
}
}
// when "subs" goes out of scope it will decrement the reference count on each item in the map. If the item wasn't copied over g_subMap, it gets deleted.

trying to use my custom class constructor without new [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 7 years ago.
Improve this question
coming from java i would like to not have to deal with de-allocation when creating new custom or other library's objects.
today i was trying to create an instance of my entity object like:
entity cube = new entity("entityName")
because this is how entity's constructor is formatted
but i get the following error:
cannot convert from |entity *| to |entity|
i noticed there are no errors if i just remove the new keyword, and i was wondering two things.
what does the error while using new mean ? (i'm pretty confident with how pointers work but not completely as i started with java.)
is it ok for me to create objects like that without the new keyword or is an object even created? (because there are no errors.)
new entity("entityName")
means "create an instance of entity in the free store and return a pointer to that instance".
Since a pointer to an entity is not the same as an entity, you cannot initialise an entity with that value unless you have yet another constructor.
The way to do what you want is
entity cube("entityname");
And you need a good book on C++.
First, I suggest you to read a C++ tutorial. It has much more complexity than Java.
This is a very partial Java to C++ "how to convert" guide that I can give you:
Java code:
void sayHello(String name) {
system.out.println("Hello, " + name);
}
public static void main(String args[]) {
String name = "James"; // <-- This string is of course created in the dynamic memory
sayHello(name); // <-- "name" will be passed by reference to the "sayHello()" method
}
Equivalent in C++ - option 1:
void sayHello(const std::string &name) {
std::cout << "Hello, " << name << std::endl;
}
int main() {
std::string name("James"); // <-- Variable is created on the stack
sayHello(name); // <-- Although "name" is not a pointer, it will be passed by reference to "sayHello", as "name" is defiend there with "&", which means that it is a reference
}
A reference is a very "weird" type - it behaves like a local variable, although it actually points to an instance that does not have to be on the stack of the current function or on the stack at all.
C++ - option 2:
void sayHello(const std::string *name) {
std::cout << "Hello, " << *name << std::endl; // <-- dereferenceing "name" using a preceding star, as "cout" needs the variable itself and not its address
}
int main() {
std::string *name = new std::string("James"); // <-- Instance is created in the dynamic memory
sayHello(name); // <-- Sending the pointer "name" to the "sayHello" function
// You will need to free "name" somewhere in the code unless you don't care about memory leaks
}
There are more options, like passing the instance by value (not recommended in such case), or like creating it in the dynamic memory and deref
what does the error while using new mean ? (i'm pretty confident with how pointers work but not completely as i started with java.)
No. C++ is different about this, you don't use an allocation (new) to initialize cube:
entity cube("entityName");
is it ok for me to create objects like that without the new keyword or is an object even created? (because there are no errors.)
No. See above. ("because there are no errors." I doubt this, there should at least be compiler warnings if you assign entity from a pointer.)

Returning a pointer in C++ [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 8 years ago.
Improve this question
I think my question sounds stupid and welcome downvote on me. If you are implementing a method in C++ which needs to return a pointer, is it safe to do that? If not, why?
Not a simple question. For instance: Best way of returning a pointer.
Ideally, you should try to avoid returning values that come with side-effects or obligations.
// This may be ok, it implies no burden on the user.
Manager* GetManager();
// But what if the user decides to call delete on the value you return?
// This is not unusual in C code, but carries a hidden contract:
// I allocate - you free.
const char* GetFilename(int fd)
{
char* filename = malloc(256);
sprintf(filename, "/tmp/tmpfile.%d", fd);
return filename;
}
C++ is about encapsulation and abstraction. You can codify the contract with your consumer by encapsulating a pointer you want to return. The idea here is that instead of exposing a pointer, you expose an object which is responsible for ownership of the pointer. Infact, recent versions of the language already do this for you with std::unique_ptr, std::shared_ptr and std::weak_ptr.
But a crude, simple RAII example might be:
class StrDupPtr
{
char* m_alloc;
public:
StrDupPtr(const char* src)
: m_alloc(strdup(src))
{}
~StrDupPtr()
{
free(m_alloc);
}
operator const char* () const { return m_alloc; }
// etc.
};
You're still returning a pointer here, but you've encapsulated it with a management contract and removed burden from the end-user to manage your resources.
You can't always avoid it, and when you have to, yes it can be dangerous.
int* AllocateMeSomeMemory()
{
int* memory = malloc(4 * sizeof(int));
// here, have four ints.
return memory;
}
int main() {
int* memory = AllocateMeSomeMemory();
memory[42] = 0xDeath; // yeah, it's not a valid hex number, but that's not really the problem.
}
Another common problem with pointers is that there's no way to tell how many people have them. Here's a contrived example:
void transferItem(userid_t user1, userid_t user2, itemid_t item) {
Account* a1 = GetAccount(user1);
Account* a2 = GetAccount(user2);
if (a1 != a2) {
transferItemInternal(a1, a2, item);
}
delete a2;
delete a1; // Sorry Dave, I can't do that. How about a nice game of CRASH?
}
Normally, a2 and a1 will be different, but when they're not...
Another common failure pattern with pointers is asynchronous callbacks:
// ask the database for user details, call OnLoginResult with userObj when we're done.
void login(int socket, userid_t userId, passwordhash_t pass) {
User* userObj = GetUserObj(userId, socket);
Query* query = Database()->NewQuery("SELECT * FROM user WHERE id = ? AND password = ?", userId, pass);
Database()->Queue(query, OnLoginResult, userObj);
}
void OnDisconnect(int socket, int reason) {
User* userObj = GetUserBySocket(socket);
if (userObj) {
UnregisterUserObj(userObj);
delete userObj;
}
}
void OnLoginResult(void* param) {
User* userObj = static_cast<UserObj*>(param);
// all well and good unless the user disconnected while waiting.
...
}
Yes it is. I assume you mean "Allocate and return" a pointer.
Its common to have initialisation functions which allocate a pointer to an object of some type, and then initialise the object itself. It will then be up to a different part of the program to release the memory.
Well it always depends on what you are doing. A pointer is simply a memory address, so it is similar to simply returning an integer. You should do more research on pointers and how to properly implement them
I sense this question might be closed quite soon, but I'll try to answer anyway.
Yes, it's "safe", as long as you're careful. In fact, it's a very common way to do things, particularly if you're interfacing with C APIs. Having said that, it's best to avoid doing so if you can, because C++ generally provides better alternatives.
Why should you avoid it? Firstly, let's say you have a method that looks like this:
MyStruct* get_data();
Is the return value a pointer to a single instance of MyStruct, or the start of an array? Do you need to free() the returned pointer? Or perhaps you need to use delete? Can the return value be NULL, and what happens if it is? Without looking at the documentation, you have no way of knowing any of these things. And the compiler has no way of knowing either, so it can't help you out in any way.
Better options:
If you want to return an array of values, use a std::array (if the size is fixed at compile-time), or a std::vector (if the size isn't known till run-time).
If you're trying to avoid copying a large struct, then return a reference, or a const reference if possible. That way the caller knows they won't receive a NULL value.
If you really need to return a pointer, than consider using a smart pointer instead -- that will help you sort out ownership issues. For example, std::shared_ptr uses reference counting, and std::unique_ptr ensures that a given pointer only ever has one owner.