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 8 years ago.
Improve this question
Hello I have three classes
AbstSoccerTeam
PlayersSoccerTeam
PlayersFieldPlayerStates
PlayerSoccerTeam is a child class of AbstSoccerTeam.
bool AlanSoccerTeam::isClosestTeamMemberToSupportingPlayer(FieldPlayer* plyr)
is a method in player soccer team.
i am trying to call that method in the PlayersFieldPlayerStates class with this
PlayersSoccerTeam* sTeam;
sTeam->isClosestTeamMemberToSupportingPlayer(player);
I can get this problem when i run it
uninitialized local variable 'sTeam' used
I dont know whats going on or why i am getting this error.
Any help is apprecitated greatly
Thanking You
The problem is you have created a pointer to a PlayersSoccerTeam but you have not actually created the object itself yet.
I would suggest doing this.
PlayersSoccerTeam sTeam;
sTeam.isClosestTeamMemberToSupportingPlayer(player);
You could alternatively do this.
PlayersSoccerTeam* sTeam = new PlayersSoccerTeam()
sTeam->isClosestTeamMemberToSupportingPlayer(player);
As perhaps an interesting education experience create a constructor that prints something to stdout when it is run and then try doing these two options and yours to see what happens. A constructor will be run whenever a new object is created.
PlayersSoccerTeam* sTeam;
This line declares a pointer to a PlayersSoccerTeam and nothing else. All you get from this line is a pointer. It doesn't point anywhere in particular since you haven't initialized. There is no PlayersSoccerTeam anywhere to point to.
If you want an object of type PlayersSoccerTeam, then you just want:
PlayersSoccerTeam sTeam;
sTeam.isClosestTeamMemberToSupportingPlayer(player);
Since you told us about your hierarchy, it's possible that you want to use your PlayersSoccerTeam polymorphically as a AbstSoccerTeam. In this case you would need to use either a pointer or reference. This could be done like so:
AbstSoccerTeam* sTeam = new PlayersSoccerTeam();
// ...
delete sTeam;
Note that this still declares just a pointer, but the expression new PlayersSoccerTeam also creates a PlayersSoccerTeam object for the pointer to point to. Note that it's perfectly fine to assign a pointer to a PlayersSoccerTeam to a pointer to its parent AbstSoccerTeam - this is polymorphism in action. If you do this, you must make sure you delete sTeam; later, otherwise the object will be leaked.
A safer way to handle the user of dynamically allocated objects is to use a smart pointer, which you could do like so:
std::unique_ptr<AbstSoccerTeam> sTeam(new PlayersSoccerTeam());
Now you will not have to delete it because the std::unique_ptr takes care of that for you.
Related
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 3 years ago.
Improve this question
I am still a beginner in c++, but I know something. I am studying the 1st term and I wanna make my own project, IMO it's the best way to learn to program. Anyway I wanna load data from file to dynamic array (and I know how to do that) but I to that job be done by special function and to that array be visible for other function (alternativity global). I know that using global variables is not good idea so I am thinking if it's possible to make variable friend with NO classes (bc I didn't use and learn classes yet)
Thanks in advance!
friend is not what you're looking for. A variable is just a named object. What you want to do here is not to somehow access the function's variable from the outside (that's not actually possible, function variables only exist when the function is executing). You want to transfer the object from one function to th other. That's done through the function's return value:
std::vector<int> readDataFromFile() {
std::vector<int> data;
// Read the file and store it into `data`
return data;
}
int main() {
std::vector<int> myData = readDataFromFile();
// Use `myData` as needed
}
You can see above that readDataFromFile works on its data variable, then returns it. This means that, right as readDataFromFile ends, myData in main (another, independent object) is initialized from data, and the data itself lives on.
Notes:
Do not use C-style arrays, new or delete. These are meant for compatibility with C and low-level memory management, not general use. A C++ dynamic array is an std::vector<YourType>.
Further notions:
Here myData is move-initialized, which means that no copy of the data is made: the dynamic array is transferred directly from data to myData
This is a case where NRVO can occur. That's an optimization which notices that data is redundant, and will replace it with direct access to myData, so there will only ever be one vector object throughout the program's execution. This is not observable in the general case., wo you don't need to worry about it.
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 5 years ago.
Improve this question
For some reason, I have decided to never use dynamic memory allocation in my program. This means all the variables in my program are static and the "new" constructor is never used. But the following code crashes, and produces a stack overflow exception:
VeryLargeObject x; // Global variable -> static memory
void ResetTheObject()
{
x = VeryLargeObject();
}
Obviously, all I want to do is give x the default value of VeryLargeObject, which is a structure containing a lot of different variables, with their own constructors of varying complexity (so there's quite some initialization work to do). But here the language/compiler has decided that this should happen on the stack before being copied, and since VeryLargeObject is too large for the stack, my program crashes.
However I have found the solution to this problem:
VeryLargeObject x;
void ResetTheObject()
{
new (&x) VeryLargeObject();
}
I had never heard of this before, yet it does exactly what I want. This is a "placement new". It calls the constructor on the already allocated (or simply static) memory provided by a pointer.
My question, since I have the solution, is a rant: Why isn't this the default behavior of the first code ? If there isn't a less hacky way of doing this (i.e without the word "new" having anything to do with it), then why? Also why does it send me back the pointer, even though I just provided it? I thought C++ was a great language, but this seems kind of ugly and not very well-thought-out.
First of all, turning on optimization might get you what you want with the first syntax. Without it, here's what you asked the compiler to do:
Create a temporary object of type VeryLargeObject.
Assign that into a global variable called x.
Since temporary objects need storage, the compiler allocates them on the stack. What the compiler is doing is, literally, what you asked the compiler to do.
The compiler may, if optimizations are turned on, understand that what the sequence is and save the copy. This requires that the compiler can positively prove to itself that the old value of x will not get in the way in any way. Since you admit that the initialization is quite complex, you can forgive the compiler if it did not manage to do so.
You have two options. You can either create an in-place initialization function and call that instead of the constructor, or you can use placement new, like you did.
The danger with placement new, as you used it, is that it replaces the old value of x without properly destructing it. It simply assumes that x is uninitialized. If that's okay for your use, then go ahead and use it. The compiler, for its part, is not allowed to assume that.
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
EDIT I don't need a solution to a problem, I want to know if and why I should prefer one thing over another. The function declaration can not change.
I have a C++ project and I need to write some code that will be called by code written in C. I have a class called A, and I need to implement a method that destroys such an object that was allocated by new, and nullify the pointer itself.
The declaration looks like this:
void destroy_A(void** a);
I need a void** so I can nullify *a.
Which of the following should I use (if any), and why?
delete *(A**)a;
delete *((A**)a);
delete (A*)*a;
EDIT: Maybe I wasn't clear: I don't know the technical terms, but I do use delete and not free, and the actual methods are called via code compiled in C. Otherwise, I wouldn't need the void**.
This is my CS faculty requirements, I didn't write the assignment :)
All three of them work. What you are looking for, in the end is
A* somePtr = ...; // get a pointer to your object
delete somePtr; // delete the object it points to
Your three options are copied below, and each one is broken up into multiple lines to highlight what they are doing:
delete *(A**)a;
A** ptrToPtrToA a = (A**)a;
A* ptrToA a2 = *ptrToPtrTo_a;
delete ptrTo_a;
No problem here. We ended up properly dereferencing the object
delete *((A**)a);
A** ptrToPtrTo_a = (A**)a;
A* ptrTo_a = *ptrToPtrTo_a;
delete ptrTo_a;
Hey, this one is exactly the same! The only thing the parenthesis do is change the order of operations. You happened to use the "native" order, so the parenthesis did nothing at all.
delete (A*)*a;
void* ptrTo_void = *a;
A* ptrTo_a = (A*)ptrToVoid;
delete ptrTo_a;
This also worked, it just took a different path.
Which one is correct? It's really a stylistic choice. I will give you my stylistic rule of thumb: always cast void pointers on separate lines. It makes it much clearer what is going on.
A* myObject = (A*)*a; // I prefer this one in this case, but what matters...
delete myObject; // ... is that it is distinct from the delete...
*a = 0; // ...not which cast is "best."
I like to do this because I find casting to/from void is a very tricky business when you really get down to it. There are a lot of places where it can go wrong. I like to create a clear line of code where I can mentally break apart all of my casting and make sure it does what I expect. Since I specify the type of the variable I want (myObject is a A*, and there's nothing the compiler can do to make it otherwise if I mess up), I am more likely to get a compiler error if I do something wrong. Its very easy to write casts from void where the compiler silently does a conversion you didn't expect. Then you're fixing a runtime error instead of a compile time error.
I also like to use that cast line as a good place to put comments explaining why I think it is safe to do the cast in the first place, such as "the only void pointers passed to this function are those created by my function in this same .cpp file, so I KNOW exactly what type is safe to cast to."
delete ptr is never going to compile in C. If it were, the first option would be correct, and the second option would be identical to it.
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
I'm trying to make a linked list with a set of data and I'm wondering if there's a way to make a variable's address change. Something like:
for(int i=array.size()-1;i>=0;i--)
{
Node *previous_ptr;
Node *current_ptr = new Node(array[i], previous_ptr);
previous_ptr=current_ptr;
delete current_ptr;
}
So I want current_ptr's address to change (allocate a different spot of memory) so the linked list gets constructed if that's possible. And I can't use alloc for it only new and delete.
Calls of new produce different addresses every time you call it, unless you call delete, in which case the memory becomes reusable, so operator new can return it again.
Your code creates hanging pointers: when you call delete on line 3
Node *current_ptr = new Node(array[i], previous_ptr);
previous_ptr=current_ptr;
delete current_ptr;
the value of current_ptr and previous_ptr immediately become invalid. At the same time, the pointer returned by new becomes eligible for reuse, so you get the same pointer when you call new again.
You should not call delete on anything that you plan to use again.
In addition, previous_ptr declared inside a for loop is not useful, because its value is thrown away on each iteration. If you would like to keep that pointer between iterations, declare it outside the loop.
As far as I know, you cannot change a variables address and it doesn't make any sense to me, if you think about what is happening in the background.
If you need a different address for your data, allocate new memory, store your data a 2nd time and delete the old data.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Closed 8 years ago.
This question appears to be off-topic because it lacks sufficient information to diagnose the problem. Describe your problem in more detail or include a minimal example in the question itself.
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.
Improve this question
I have a class really complicate, it has inside a vector of another class. I report one simpler, anyway it has inside the problem which I've been able to find.
// the inner class
class DuffyDuck{
int isblack; // 0 is white, 1 is black
int n_duck;
vector<DuffyDuck> * point_Duck;
public:
DuffyDuck(int isblack):isblack(isblack){
}
void set_point(vector<DuffyDuck> & Abitants){
point_Duck=&Abitants;
}
};
// the complessive class
class DuckCity{
vector<DuffyDuck> DuckAbitants;
public:
DuckCity(int numwhite,int numblack){
for(int i=0;i<(numblack+numwhite);++i){
DuckAbitants.push_back(DuffyDuck(i>=numblack));
DuckAbitants[i].set_point(DuckAbitants);
}
}
};
Now this works (i use point_Duck in several functions) but if I do something like that shown after once it's called in example "(*point_Duck)[2].n_duck;" in a function the project crashes.
That happens only if I do that:
DuckCity LittleTown(0,0);
LittleTown=DuckCity(3,5);
And after using some functions which call pointer.
If I do directly LittleTown(3,5) all is right.
I hope I explained well enough.
The DuffyDuck class is storing the address of a vector<> member of a DuckCity. Thus, when you copy the DuckCity to a different instance, that new instance will have a different vector<> instance. However, each DuffyDuck instance in that vector still has the address that was part of the old DuckCity instance.
So, your copy into littleTown yields dangling pointers.
I would recommend that you either rethink your design of DuffyDuck, or implement an assignment operator for DuckCity that performs a deep copy for each element of the vector<>. If you implement an assignment operator, remember to also follow the Rule of Three.
The cause of the problem is that each DuffyDuck has a pointer to a vector of DuffyDuck(s). When the class is destroyed the references become invalid --> crash.
DuckCity littleTown(1,2); // this creates a duck city
// with each duck pointing to the DuckAbitans vector.
littleTown=DuckCity(3,5); // this initializes another instance (call it INST)
// of DuckCity and
// then it assigns (via = operator) the value to littleTown
// by **copying** the DuffyDuck structures into a newly
// allocated vector. This makes the pointer of each DuffyDuck
// invalid after INST is destroyed (as it is a temporary object)
When you copy the address of Abitants, you are taking the address of the vector in the temporary object created by DuckCity(3,5). This temporary object is then copied into littleTown, and the original object destroyed. This means your original Abitats pointer is pointing at unused memory, which in turn leads to a crash.
It's hard to say exactly how you should fix this - probably by having a copy-constructor that "reconstructs" the Abitats pointer.