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.)
Related
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 ) );
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 4 years ago.
Improve this question
I am building a project that is composed of Vehicle, Showroom, and Dealership. I've built the classes, and I am testing out my method GetAveragePrice()
float Dealership::GetAveragePrice()
This method was working perfectly:
Dealership dealership("COP3503 Vehicle Emporium", 3);
dealership.AddShowroom(&showroom);
dealership.AddShowroom(&secondary);
dealership.AddShowroom(&third);
cout << "Using just the GetAveragePrice() function\n\n";
cout << "Average price of the cars in the dealership: $" << std::fixed << std::setprecision(2);
cout << dealership.GetAveragePrice();
The output would be
Using just the GetAveragePrice() function
Average price of the cars in the dealership: $27793.60
This is the expected output I wanted, but I was told I have memory leaks and must include a destructor to deallocate my *Showroom showroomList pointer (which I initialized as the following in the Dealership constructor):
this->showroomList = new Showroom[maxNumOfShowrooms];
So I write my destructor as the following:
Dealership::~Dealership()
{
delete [] showroomList;
}
Now, there aren't any memory leaks, but I don't get the expected output and an exit code 11:
Using just the GetAveragePrice() function
Process finished with exit code 11
Does anyone know why this destructor is messing up my output?
This version would delete only once by the last instance standing, in its destructor.
std::unique_ptr<ShowRoom> Dealership::showroomList;
Dealership::Dealership(size_t maxNumOfShowrooms)
:showroomList(std::unique_ptr<ShowRoom>(new Showroom[maxNumOfShowrooms]))
{
}
Dealership::~Dealership()
{
// auto deleted here, with reverse order of initialization
}
but you have a new and delete pair so you should check for deletion only once. This would need some global counter outside of class (or its static variable) and this may not be as readable as smart pointer.
If you are using multiple threads with this, then you could be better with shared_ptr and a custom deleter ([](T * ptr){delete [] ptr;}) as its second constructor parameter.
At least this way you can know if error is about new and delete.
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 5 years ago.
Improve this question
This is basically my main function :
void GameObject::deserialize(QList<GameObject*> *list)
{
QFile _file(_filename);
if (!_file.open(QIODevice::ReadOnly | QFile::Text))
{
qDebug() << "Couldn't open file to read";
return;
}
QTextStream in(&_file);
while (!in.atEnd())
{
QString currentline = in.readLine();
if (currentline.startsWith("GameObject {"))
{
list->append(getGameObject(&in, currentline));
}
}
_file.close();
}
It opens a file, and parses it for GameObjects.
The getGameObject (cleaned up) function is this one :
GameObject *GameObject::getGameObject(QTextStream *in, QString current_line)
{
GameObject *go = new GameObject();
QList<GameObjectVariable*> govl;
bool ok;
while (!in->atEnd() && !current_line.startsWith("} end GameObject"))
{
current_line = in->readLine();
if (current_line.startsWith("GameObjectVariable")) {
GameObjectVariable *gov = this->getGameObjectVariable(in, current_line);
govl.append(gov);
go->setVariableList(&govl);
qDebug() << QString("AR : Type As String of the returned object : ") + gov->getTypeAsAString();
qDebug() << QString("AR : Type as number : ") + QString::number(gov->getType());
if (gov->getType() == NUMBER_LIST) {
qDebug() << "Number List";
qDebug() << QString("Value as a string of the number list : ") + ((GameObjectVariableNumberList*)gov)->getValueAsAString();
}
else if (gov->getType() == STRING_LIST) {
qDebug() << "String List";
qDebug() << QString("Value as a string of the string list : ") + ((GameObjectVariableStringList*)gov)->getValueAsAString();
}
else if (gov->getType() == GAMEOBJECT) {
qDebug() << "GameOBject";
qDebug() << QString("Value as a string of the gameobject : ") + ((GameObjectVariableGameObject*)gov)->getValueAsAString();
}
}
}
return go;
}
This one basically is a big mess of ifs, but it works, up to a point. The goal of this function is to read line by line, and return a gameobject filled with the read info. This is a weird format we use for the project though.
The last bunch of lines are Debug lines I've put in to try to understand where the problem was.
This is the other (cleaned up) function that's related :
GameObjectVariable* GameObject::getGameObjectVariable(QTextStream *in, QString current_line)
{
GameObjectVariable *gov;
bool ok;
int type;
QList<QString> ls;
QList<int> ln;
QList<GameObject*> lgo;
while (!in->atEnd() && !current_line.startsWith("} end GameObjectVariable")) {
current_line = in->readLine();
if (current_line.startsWith("type: "))
{
type = current_line.right(current_line.size() - 5).toInt(&ok, 10);
}
else if (current_line.startsWith("value: ")) {
if (current_line.startsWith("value: {"))
{
while (!in->atEnd() && !current_line.startsWith("} end value"))
{
current_line = in->readLine();
if (!current_line.startsWith("} end value"))
{
if (type == GAMEOBJECT_LIST)
{
lgo.append(getGameObject(in, current_line));
}
else if (type == STRING_LIST)
{
ls.append(current_line);
}
else if (type == NUMBER_LIST)
{
ln.append(current_line.toInt(&ok, 10));
}
}
}
if (type == GAMEOBJECT_LIST)
((GameObjectVariableGameObjectList*) gov)->setValue(&lgo);
else if (type == STRING_LIST)
((GameObjectVariableStringList*) gov)->setValue(&ls);
else if (type == NUMBER_LIST)
((GameObjectVariableNumberList*) gov)->setValue(&ln);
}
}
}
qDebug() << QString("BR : Get the type as string : ") + gov->getTypeAsAString();
qDebug() << QString("BR : Get the type as number : ") + QString::number(gov->getType());
qDebug() << QString("BR : get the value as string of the object : ") + gov->getValueAsAString();
return gov;
}
This function reads the lines in the GameObjectVariable 'tag'. The type is a defined int that is macroed to the text type we use for the other if forest.
Now this again works fine, except for when we have a list of values (the part that starts with else if (current_line.startsWith("value: {"))).
The debug lines at the end of the function (the "BR :" ones) show the object properly filled, but the ones at the end of the getGameObject calling function (starting with "AR :") crash, because apparently the value is null.
GameObjectVariable object is this one (again, cleaned up) :
class GameObjectVariable
{
public:
GameObjectVariable(QString name, QList<int> idListEdit = QList<int>(), QList<int> idListView = QList<int>());
// GETTERS
QString getName() {return this->name;}
int getType() {return this->type;}
void *getValue() {return this->value;}
// SETTERS
void setName(QString name) {this->name = name;}
void setValue(void* value) {this->value = value;}
QString getTypeAsAString();
virtual QString getValueAsAString() = 0;
private:
QString name;
protected:
void *value;
int type;
};
getValueAsAString is set as virtual because every type mentioned in the code above (like GameObjectVariableStringList overwrite this one with a return of their value with the correct type)
Finally, here is an example of file we try to deserialize :
GameObject {
name: Number 1
type: Test
GameObjectVariableStringList: {
type: 3
name: List String
value: {
String 1
String 2
} end value
} end GameObjectVariable
(type: 3 corresponds to STRING_LIST)
The main problem is bolded.
The problem
getGameObjectVariable()'s local variable GameObjectVariable *gov is an uninitialised pointer, which you suddenly cast to some other type and then start trying to call methods on.
How did you expect that to end? You are telling the compiler this: Poke at random memory as if it holds an allocated, initialised object. Also, this object might have any of 3 different types.
Seriously: What did you think was happening in that function, that it was somehow producing a usable object? I'm genuinely curious.
Anyway, for at least three reasons, this is malformed code that exhibits completely undefined behaviour:
The pointer is uninitialised, so like any uninitialised variable, reading/dereferencing it is UB.
No object is alive at the (invalid) address to which it points, but you call methods on it as if an object lives there; that is UB.
Said methods then presumably start writing stuff to whatever arbitrary address you happened to end up at, with no permission, which is lethal UB.
(Also, even if there was valid memory to access and a valid object at it, casting the pointer to another type then using it is only valid if an instance of that other type was specifically allocated at that address - or some more-derived one, but then the C-style cast is (A) bad style and (B) potentially very dangerous if e.g. multiple and/or virtual inheritance are in play.)
Due to all this UB, anything can happen, or nothing might happen, or exactly what you want just might happen - but the code is fundamentally broken.
For example, as seems to have occurred here, the compiler might coincidentally act like there is a valid object while within the same function, but then you return that garbage pointer to getGameObject(), and it suddenly reveals that you fed it rubbish.
UB gives the compiler, and particularly its optimising layers, free reign to do whatever they want, chiefly because they are allowed to assume UB does not happen. So, e.g. they can assume there must be a valid object pointed to by gov, even if there blatantly isn't. That assumption gets lost after you return, though, for whatever reason.
Who knows? The precise reasons for the observed behaviour are pretty uninteresting to speculate about. You can produce assembly output if you really want to know why what happened happened.
The (immediate) solution
But the key point is this: You need to replace this particular mess with proper, valid code - and fast. So, you need to assign a valid value to the pointer, by assigning it the address of a newly allocated object of whichever type is required. Only then do you have an address to which you are allowed access, with a living object at it, of the right type. It's then OK to create a cast pointer of the real derived type to call derived methods, but return a pointer-to-base for others to use.
Conditionally calling methods, etc.
Also, those conditional casts and calls to setValue() look suspicious. Why not just make that a virtual method and let the compiler resolve the right variation? Generally, if you have some conditional construct deciding which method to call based on the real type... You should just use virtual functions. Most concern about their overhead is FUD, and most attempts to avoid that overhead are no more efficient to execute and much worse to read.
For instance, do you expect all users of any GameObjectVariable to repeat the same hoop-jumping exercise of checking what type it is and casting to the equivalent type of pointer to call the right (derived, hiding-not-overriding) version of setValue()? Hello, boilerplate spaghetti code, for no reason.
I think this points at more general bad patterns in your design. Rather than having huge functions that repeatedly have to check the type and do different things, with different lists depending on the type, etc. - why not simply check the type specified by the input line, and construct a new object of that type with, for example, the rest of the line as an argument, letting it create and populate whatever type of list and any other specific attributes it needs? Then you'll have tidy methods that do single things, not labyrinths that must constantly remind themselves what kind of object they're working with.
Avoid new
Note that I said said to assign the pointer from "a newly allocated object", not a newly allocated object... Most people should not ever need to use raw new or delete in C++, so you should return a unique_ptr, ideally from std::make_unique<Foo>(args).
There is a fair exception if, as hyde points out in the comments, your new object is of a type that should have its lifetime managed by a parent object to which it is then added. Then new is OK - assuming there's no better way to phrase it, like I dunno, make_floating_reference<Foo>(args). But, as hyde also said, that isn't the case for your GameObjectVariable, so a smart pointer is the way to go for that.
(Normally I would say you probably don't need dynamic allocation at all, but since you appear to need polymorphism and the objects clearly don't comprise a known set on the stack to which you could push non-owning pointers/reference-wrappers into the container, it seems that you do.)
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 8 years ago.
Improve this question
Yes I have read a lot of tutorials and questions and also tried a lot of combinations but it seems not to work.
My goal is not to use dynamic allocation.
My classes look like this:
Pages
Page
PMain:Page
PCam:Page
on my main when I do this:
1.
main:
Page * page;
PCam main;
main.setContext(context);
page = &main;
page->echo();
result: PCam
but when I try to create the instance inside an outside class and point it to page it fails.
2.
pages class:
Pages::Pages(Page*& page, Context& context){
this->context = &context;
PMain main;
main.setContext(*this->context);
main.echo();
// page = &main; <---
}
main:
Page * page;
Pages pages(page, context);
page->echo();
result: Page
expected result: PCam
My classes:
Page:
void Page::setContext(Context & context)
{
this->context = &context;
}
void Page::echo() //virtual
{
std::cout << "echo Page" << std::endl;
}
PMain:
void PMain::echo(){
std::cout << "echo PMain" << std::endl;}
}
PCam:
void PCam::echo(){
std::cout << "echo PCam" << std::endl;}
}
Any help would be appreciated. thanks.
Your problem, or one of them, is that this:
Pages::Pages(Page*& page, Context& context){
[...]
PMain main;
is a local stack variable. When this function returns, it ceases to exist.
If you've assigned it to a pointer, you'll get undefined behavior by using it.
My goal is not to use dynamic allocation.
Unless you have some specific reason, this is a mostly pointless goal. If you want a pointer to a stack object (i.e., one that's not dynamically allocated), that object must remain in scope as long as you use the pointer. If you can't do that, then you need to put it on the heap (i.e., dynamically allocate).
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.