I am doing some assignment and i am not good at understanding pointers. Please help me understand what argument i need to pass to this function.
void City::setList(List<City*> *l){list = l;}
Without seeing the definition for List (and because Google is case-insensitive), I can't give an exact answer, but you'll want to construct it something like this:
List<City*> myList;
Then (assuming List works like Java's List):
City c; //Or with constructor, or whatever
myList.add(&c);
To call your method:
// `d` is some other City
d.setList(&myList);
There's one major caveat, though: Unless you created c with new (which, given the syntax example I used here, you probably didn't), any pointers to it are going to be dangling as soon as c goes out of scope. You'll want to make sure you aren't doing that. And if you create it with new, you have to be sure to delete it later.
Related
I read other questions trying to figure this out but I didn't find much like what I have in mind. I'm kinda new to C++ and I just don't want to have my C++ code to look like "C with classes", or in other words, if there is a good "C++ way of doing this", that's what I'm looking for, but I'm a bit confused. Well, to the problem.
I have a class, say MyClass. Now, in other class, say MyContainer, I have a vector<MyClass> vec.
Let's say I'm now creating a method that populates a MyClass object with any arbitrary stuff and then pushes it into vec. First question is: should I allocate and push the object like the following? (using vector<MyClass> vec)
MyClass *obj = new MyClass(args);
vec.push_back(*obj);
I am not sure this is right, but by my understanding, this could make me avoid having to manually delete every instance of MyClass I put into vec when the instance of MyContainer is of no use anymore.
What bugs me is that, like I said, this does not seem right anyway, and the other way I can figure out is declaring vector<MyClass*> and writing:
MyClass *obj = new MyClass(args);
vec.push_back(obj);
But this would make me write a method to delete every instance of MyClass I created before, right?
So... What should I use and, if both are actually right, when one is preferrable to the other?
However, if everything is wrong from the start, how can I do this?
Thank yall!
PS: by the way, MyContainer is created in main(). I'm planning to use heap allocation. Should I?
Edit: I can't use C++11.
PS2: This is part of an assignment, but I found it general enough to be of use for anyone, not just me.
You probably shouldn't use new unless you need the object to survive beyond the local scope of the variable.
Just declare it on the stack:
MyClass obj(args);
vec.push_back(obj);
In C++11, you can avoid any risk of extra copies of obj by using:
vec.emplace_back(args);
Whether or not you should allocate on the heap or the stack as suggested by #happydave is highly dependent on the nature of "MyClass", IMO. If you need any kind of polymorphic behavior (i.e. you might have specialized subclasses of MyClass), then you should have a container of pointers.
If you're concerned about needing to delete each of the entries individually, there are two things that might help you:
1 . Use shared_ptr. So your code might look like this:
typedef std::shared_ptr<MyClass> MyClassPtr;
...
vector<MyClassPtr> vec;
vec.push_back(MyClassPtr(new MyClass());
The smart pointer will automatically delete MyClass when there are no more references to it.
2 . If you use bare pointers, you can still delete all the pointers with one line of code using std::for_each. This is described here: Can I call `delete` on a vector of pointers in C++ via for_each <algorithm>?
If you don't need polymorphic behavior and your class is copyable (either you gave it a copy constructor or the default copy is good for your implementation), then you can allocate on the stack.
So after working on my last question, I boiled it down to this:
I need to add an unknown number user-defined classes (object_c) to a boost::intrusive::list. The classes have const members in them. All I need to do to push them to the list is to construct them and then have them persist, they automatically add themselves.
The code in question is basically
for (unsigned i = 0; i < json_objects.count(); ++i) {
ctor_data = read(json_objects[i]);
// construct object here
}
What I've tried:
mallocing an array of objects, then filling them in: Doesn't work, because I have const members.
static object_c *json_input = (object_c*) malloc(json_objects.size() * sizeof(object_c));
...
json_input[i](ctor_data); //error: no match for call to (object_c) (ctor_data&)
Making a pointer: This doesn't work, functions don't work properly with it, and it doesn't get destructed
new object_c(ctor_data);
Pushing the object back to an std::vector: This doesn't work, boost rants for dozens of lines when I try (output here)
vector_of_objects.push_back(object_c(ctor_data));
Just declaring the darn thing: Obviously doesn't work, goes out of scope immediately (dur)
object_c(ctor_data);
I'm sure there is an easy way to do this. Anyone have any ideas? I've been at this problem for most of the weekend.
#3 should be the method you need to use. You need to elabourate on what your errors are.
If it is just operator= as you show in your previous question, and you dont want to define one, you can try emplace_back as long as you are in C++11. Of Course I am talking std::vector, I need to check what is the equivalent if any in boost::intrusive. Edit: I might be wrong, but it doesnt seem to support move semantics yet..
Alternatively use #2 with smart pointers.
If you are going with #1, you would need to use placement new as #rasmus indicates.
At the end of the documentation's usage section it tells you that
“The lifetime of a stored object is not bound to or managed by the container”
So you need to somehow manage the objects’ lifetime.
One way is to have them in a std::vector, as in the documentation’s final example.
Sorry for the late reply, exam studying and all that.
It was simpler than I was making it out to be, basically. Also, for this answer, I'm referring to my class as entity_c, so that an object of entity_c actually makes sense.
What I was doing in my OP was when I push_back'd an entity_c, it was automatically adding itself to a global intrusive::list, and somehow that made it not work. After I stopped being lazy, I wrote up a minimal compilable progam and played around with that. I found out that making an std::vector to store the constructed entity_cs in worked (even though it deconstructs them when they're added? I dunno what that's about). Then all I had to do was populate a local intrusive::list with those objects, then clone the local list into the global list.
Thanks for all the help, I'll tweak that program to try and fit in different stuff, like placement new suggested by #rasmus (thanks for that, hadn't seen that before). Also thanks to #karathik for showing my emplace_new, I think I might have to go and find out about all these new C++11 features that have been added in, there are so many cool ones. I even learnt how to make my own copy constructor.
Truly and edifying educational experience.
So I have declared a vector in my class header like this:
...
private:
vector<Instruction> instructions;
...
Then in the .cpp implementation in the constructor, I try to initialize it like this:
instructions = new vector<Instruction>();
Xcode tells me: No viable overloaded '='
I am basically trying to get this class to behave like I would expect in java, where instances of the class retain this vector. Thats why I wanted to dynamically allocate it using new, so as to make sure that it doesn't get lost on the stack or something. Any help would be appreciated with this, thanks so much.
In order to do what you're trying to do the instructions = new vector<Instruction>() line is entirely unnecessary. Simply remove it. The vector will automatically get default-constructed when an instance of your class gets constructed.
An alternative is to make instructions into a pointer, but there doesn't appear to be any reason to do this here.
when you write
vector<Instruction> instructions;
you already have instantiated instructions to whatever memory model the user of your class is using e.g.
class YourClass
{
vector<Instruction> instructions;
};
...
int main()
{
YourClass class1; // stack
std::unique_ptr<YourClass> class2(new YourClass); // heap
...
}
In your class, you declare a std::vector<Instruction>. new vector<Instruction>(); returns you a std::vector<Instruction>*.
operator new returns a pointer, so you have a type mismatch.
The real issue is the fact that you are doing it at all. Do you have a good reason for dynamically allocating that vector? I doubt it, just omit that entirely as it will be allocated along with instances of your type.
You have a member value but you try to initialize it from a vector<Instruction>*. Initialize it from vector<Instruction> or change the declaration to a pointer. If you go down the second route, you need to observe the rule of three.
You might also want to get a decent C++ book from this list.
Also, I think you have a using namespace std; in your header which is bad.
Do not use new in C++ unless you know what you are doing. (Which you do not, currently.)
Instead use automatic objects. You already defined instructions to be an automatic object. You just need to init it as if it were one:
class wrgxl {
public:
wrgxl()
: instructions() // this initializes the vector using its default constructor
{
// nothing needed here
}
...
private:
vector<Instruction> instructions;
...
};
The initialization of instructions in the constructor's initialization list is optional, though, if you only want to call the default constructor anyway. So in this case, this would be enough:
wrgxl()
{
}
If you wanted to dynamically allocate a vector, you would need to make instructions a pointer to a vector. But this rarely ever make sense, since the vector already allocates its data dynamically, but wraps this, so you do not have to deal with the ugly details resulting from this.
One of those details is that, if you have a dynamically allocated object in a class, you will then have to worry about destruction, copy construction, and copy assignment for that class.
As Kerrek already pointed out, you will need to have a good C++ book in order to properly learn C++. Make your pick.
I think you are confusing C++'s with C#'s syntax.
First, unlike in many languages, variables allocated on the stack (such as yours), are initialized by calling the default constructor, so I suspect that what you are doing is unnecessary.
Second, in order to do what you are trying to do, you use the following syntax:
instructions = vector<Instruction>();
however, as I said, this is likely redundant (and wasteful on a non-optimizing compiler as it might call both the constructor and the assignment operator). A much better way to do this is found in sbi's answer.
Third, unlike in C#, the new operator allocates memory on the heap and returns a pointer to the newly allocated data. Your variable instructions is not a pointer, thus the error.
I need make a class, let's say FineStack, who should declare a structure able to manage different kind of Fines ( LightFine, SeriousFine ). The superclass for both is Fine.
The question is, do I really need templates? I thought it was not necessary, so this is what I thought:
-> declare Fine *fines; ( kind-of array of fines? ) And ... creating an array of Fine's objects (the superclass), it should be able to manage both LightFine and SeriousFine objects.
-> The problem is. How should I declare it? Fine should be an abstract class, so no instances could be created (instances should be either LightFine's or SeriousFine's ).
I got stuck with this, since I don't find the way to get it. I've read in multiple questions here in Stackoverflow, that you guys usually suggest to use std::vector , which makes you easier to manage this kind of stuff.
Should I go in that way and forget about the original idea?
I need a structure which should be able to handle any object from both subclasses, in any order (let's say .. 3 LightFine and 2 SeriousFine ... or alternatively each other from the start to the end of the structure ... whatever.
I would like to point you in the right direction and not just give you the whole shebang. If this doesn't help, please ask about what's troubling you:
Although Fine cannot be instantiated, you can point to it, so:
Fine* f1 = new LightFine();
Fine* f2 = new SeriousFine();
are both legal, because LightFine is-a Fine and SeriousFine is-a Fine.
Edit: I see this is not clear yet. If you read the above you can see that I can hold a pointer Fine*, yet have it "secretly" point to either LightFine or SeriousFine. That means, If I were to keep a bunch of Fine* pointers, some of them could be LightFine and some SeriousFine. i.e, I can do this:
Fine** fines = new Fine*[5];
f[0] = new LightFine();
f[1] = new SeriousFine();
...
for (int i=0; i<5; i++) {
std::cout << fines[i]->toString() << std::endl;
}
and the output would be:
a light fine
a serious fine
...
if you do want to use a vector, it too should be of type vector<Fine*> and not vector<Fine>.
You can't have an array of Fines or a vector of fines because the Fine class is abstract (and it should really be).
The solution is to use either an array of pointers (like Fine **fines and fines = new Fine*[whatever-size-you-need]) or a vector of pointers (like std::vector<Fine*> fines). After that, you can instantiate any subclass of Fine with new and it will be implicitly upcasted to Fine* when you put it into the array/vector.
And you certainly don't need templates here, unless you have another (unrelated) reason to use them.
In C++, polymorphism (the ability to have the same code work with objects of multiple different subclasses of a given parent class) is accomplished with pointers and references to base classes, not base class types themselves. If you come from a language like Java this might be confusing, because there all object references implicitly behave like pointers do in C++.
Ideally you should use vector<std::tr1::shared_ptr<Fine> >. The Boost documentation does a good job explaining why shared_ptr simplifies memory management; TR1's shared_ptr is essentially the same as Boost's except that it probably already comes with your compiler.
If you're content to do your own memory management, use vector<Fine*>. Don't use vector<Fine> -- that will cause object slicing.
What is object slicing? LightFine is (possibly) bigger than Fine, so it won't fit in the same amount of memory. If you declared Fine a; LightFine b; a = b; this will compile, but the entire LightFine object won't fit in a, so just the Fine subobject of b will be copied. Essentially the same thing happens when inserting a LightFine object into a vector<Fine>.
You won't be able to treat a as a LightFine object after that assignment, since its static type is just Fine, and all the LightFine "parts" have been discarded anyway. Also, treating a as a Fine object can produce unexpected behaviour -- for example Fine might have an internal data field that is repurposed by LightFine and thus contains an out-of-bounds value when interpreted by Fine's methods.
Revised answer after my first had errors:
Will both LightFine and SeriousFine implement only the interface from Fine, or will they have additional methods that the FineStack will need to know about?
If the FineStack will only interact with the Fine objects using methods defined in Fine's interface, then I don't see a problem with your array approach, as long as you use Fine** fines (i.e. an array of pointers to Fines). Although, I'd tend to use a std::vector<Fine*> instead.
(I did have a comment here about dynamic_cast, but I've removed it after a couple of commentors suggested it was dangerous advice).
sounds like you should go with std::vector<Fine>
I was browsing my teacher's code when I stumbled across this:
Order* order1 = NULL;
then
order1 = order(customer1, product2);
which calls
Order* order(Customer* customer, Product* product)
{
return new Order(customer, product);
}
This looks like silly code. I'm not sure why, but the teacher initialized all pointers to NULL instead of declaring them right away(looking at the code it's entirely possible, but he chose not to).
My question is: is this good or acceptable code? Does the function call have any benefits over calling a constructor explicitely? And how does new work in this case? Can I imagine the code now as kind of like:
order1 = new Order(customer, product);
Init to NULL
[edit] since there's a valid discussion, I've changed the order of the options a bit to emphasize the recommended option.
Variables should be declared as local and as late as possible, and initialized immediately. Thus, the most common pattern is:
Order * order1 = order(...);
just before order1 is required.
If there is any reason to separate the declaration of order1 from the instantiation, like this:
Order * order1; // Oh no! not initialized!
// ... some code
order1 = order(...);
order1 should be initialized to NULL, to prevent common bugs that occur with uninitialized variables, easily introduced when // some code changes.
Factory method
Again, there's some more change resilence here: the requirements for instantiating an Order may change. There are two scenarios I can think of right off top of my head:
(1) Validation that can't be done by Order's constructor. Order may come from a 3rd party library and can't be changed, or instantiation needs to add validation that isn't within the scope of Order:
Order* order(Customer* customer, Product* product)
{
// Order can't validate these, since it doesn't "know" the database
database.ValidateCustomer(customer); // throws on error
database.ValidateProduct(product); // throws on error
return new Order(customer, product);
}
(2) You may need an order that behaves differently.
class DemoOrder : public Order { ... }
Order* order(Customer* customer, Product* product)
{
if (demoMode)
return new DemoOrder(customer, product); // doesn't write to web service
else
return new Order(customer, product);
}
However, I wouldn't make this a general pattern blindly.
It seems to me that your teacher is an old C programmer who hasn't quite shaken off some of his old habits. In the old times, you had to declare all variables at the beginning of a function, so it's not unusual to see some old timers still doing so.
If that's really all the important code, I see no benefit to the function or the initial NULL value. new works the way it always works. It constructs an Order and returns a pointer to it, which is in turn returned by order.
The code give could be important if the assignment to NULL happens in one function, e.g. the constructor, and the assignment that calls new happens in another function. Here's three reasons;
If the customer and product parameters might not be available when the order = NULL was called.
The NULL value could be significant in the interim to let other functions know that the order hasn't yet been created.
If the Order class took a lot of resources, deferring its initialising could be beneficial.
Best to ask your teacher why they did it this way. Sometimes the obvious conclusions aren't the right ones.
If the things really are as you describe them then your teacher's code illustrates some rather bad programming practices.
Your question is tagged C++. In C++ the proper technique would be to move the variable declaration to the point where it can be meaningfuly initialized. I.e. it should've looked as follows
Order* order1 = order(customer1, product2);
The same would appliy to C99 code, since C99 allows declaring variable in the middle of the block.
In C code the declaration must be placed at the beginning of the block, which might lead to situations where you can't meaningfully initialize a variable at the point of declaration. Some people believe that in this case you have to initialize the variable with something, anything just to keep it initialized as opposed to leaving it uninitialized. I can respect this as a matter of personal preference, buy personally consider it counterproductive. It interferes with compiler optimizations and tends to hide bugs by sweeping them under the carpet (instead of encouraging proper fixes).
I would say that your teacher's C++ code suffers from some bad habits brought over from C.
For the given code, there is no difference. Its better to initialize order object with a newly created object at single place. It will avoid using order variable initialized with NULL value