arkoenig 340 Practically a Master Poster

Put the try-catch inside the for loop.

arkoenig 340 Practically a Master Poster

C++ Primer 4th edition says default constructor is used regardless where a class variable is declared - does that means variable of class type is initialized whether it is global or local?

Yes, that's what it means, as long as the class has one or more constructors.

Even if the class has no explicitly defined constructor, but has a member with a type that has a constructor, then that constructor is used to initialize that member. In addition, a variable with static lifetime (which includes all variables defined at global scope) will have all of its data members initialized to 0 before anything else happens.

For example:

struct Foo {
    int x;
    std::string s;
};

Foo f1;

int main()
{
    Foo f2;
}

Here, f1.s and f2.s will both be initialized to null strings because that's what the default constructor for the library string class does. In addition, f1.x will be initialized to zero because f1 is a variable with static lifetime. On the other hand, f2.x will have an indeterminate value, and trying to use it without giving it a new value will cause undefined behavior.

arkoenig 340 Practically a Master Poster

If the result is still the same, that suggests that there are similar problems elsewhere in the program. Perhaps you should look for them.

arkoenig 340 Practically a Master Poster

The first statements you execute in your main program are

p = NULL;
add(&p,5);

The first statements you execute in add are

r=*q;
if(num<=r->data||r==NULL)
// ...

Here, q is the first parameter of add, which means that the value of q is &p as computed in main. Therefore, *q is the same value as p in main, or NULL.

When you try to access r->data when r is NULL, the result is a run-time error.

I will leave it to you to figure out (a) what the problem is, (b) how to fix it, and (c) whether there are any other problems.

arkoenig 340 Practically a Master Poster

Line 16 compares the values of the two pointers, not the values of the doubles to which they point.

Also, if your argument is const double *, that means you're promising not to change the value to which the pointer points. If you now return double *, you're violating that promise.

Fix these two problems and your ComputeMaximum function looks like this:

const double *ComputeMaximum(const double *num1a, const double *num2a)
{
    return *num1a > *num2a? num1a: num2a;
}

Because you are expecting pointers rather than references, you need to pass the addresses of the numbers in line 12. Also, you have swapped value and address:

cout << "The greatest value is: " << *ComputeMaximum(&num1, &num2) << " and its pointer is: " << ComputeMaximum(&num1, &num2);

And, of course, you need to change line 4 to match the function:

const double *ComputeMaximum(const double *num1a, const double *num2a);
arkoenig 340 Practically a Master Poster

You're right.But this is read.

Really? What leads you to that conclusion?

arkoenig 340 Practically a Master Poster
ifstream in;
in.open("filename",std::ios::app);
in.seekg(in.tellg(),std::ios::end);//this places the file pointer at the end

I don't think the last line is necessary -- once you've opened it with ios::app, every write seeks to the end.

arkoenig 340 Practically a Master Poster
ofstream f(filename, ios_base::out | ios_base::app);

iosbase::app means that you want to append to the file.

arkoenig 340 Practically a Master Poster

Note that the value returned by ip.c_str() persists only until the next time you change the value of ip . So if you modify ip in any way between the time you assign the value to argv[1] and the time you use the value, the effect is undefined.

arkoenig 340 Practically a Master Poster

Ahh i see, as the next issue i came up with was that the compiler was silent but it didnt work:P

What do you mean "it didn't work"? In the code you posted, you never actually use your Write member, so what didn't your code do that you expected it would do?

arkoenig 340 Practically a Master Poster

Your statement

Write = &WriteLogS;

should be

Write = &Logger::WriteLogS;

and similarly for the other similar statement.

arkoenig 340 Practically a Master Poster

How did I come up with it?

If you execute bullet_list.erase(iter) , that invalidates iter . So before executing bullet_list.erase(iter) , it is necessary to compute the new value to be placed into iter , because there will be no opportunity to do so later.

Here's the straightforward way to do it:

std::list<bullet>::iterator temp = iter;
++iter;
bullet_list.erase(temp);

This part of the solution is pretty simple. I guess it's a creative step to realize that

bullet_list.erase(temp++);

does exactly the same thing, and it's hard to explain why I happened to think of it.

It helps to have been using C++ for 25 years.

arkoenig 340 Practically a Master Poster

This code doesn't work:

std::list<bullet> bullet_list;
std::list<bullet>::iterator iter;

bool alive = false;
for (iter = bullet_list.begin(); iter != bullet_list.end(); ++iter) {
	bool isalive = iter->alive;
	if (isalive == true) {
		alive = iter->move(); // move is a function inside the struct "bullet"
	} 
	if (alive == false) {
		int bulletID = iter->id;
		bullet_list.erase(iter);
		dbDeleteObject(bulletID); // deletes object from game
	}
}

The problem is in line 12. Executing bullet_list.erase(iter); causes the element to which iter refers to be deleted from the list. Doing sinvalidates iter. On the next trip through the while loop, iter is invalid, so ++iter has undefined effect.

One way to deal with this problem is to increment iter only when it is known to be valid. The following rewrite is slightly sneaky, but I think it will work:

std::list<bullet> bullet_list;
std::list<bullet>::iterator iter;

bool alive = false;
for (iter = bullet_list.begin(); iter != bullet_list.end(); ) {  // No increment!
	bool isalive = iter->alive;
	if (isalive == true) {
		alive = iter->move(); // move is a function inside the struct "bullet"
	}

	// The following if statement increments iter one way or another,
	// regardless of the value of alive
	if (alive)
		++iter;
	else {
		int bulletID = iter->id;
		bullet_list.erase(iter++);
		dbDeleteObject(bulletID); // deletes object from game
	}
}

The point is that bullet_list.erase(iter++); copies iter , increments it (which causes it to refer to a value that will survive the call to erase , and then erases the element to which iter formerly referred. This …

Yiuca commented: I don't like giving broken code but it sometimes happens, thanks for correcting it. +2
arkoenig 340 Practically a Master Poster

You are exactly right about the point of the question. The question is there in order to encourage readers to stop thinking about data formats in terms of absolute sizes, and to try to write programs with output that conforms to the data being displayed.

arkoenig 340 Practically a Master Poster

You don't like how C defines integer division, and from that you conclude that it has no advantages over assembly language? Surely you're joking!

arkoenig 340 Practically a Master Poster

The book does not have answers provided because I have found that when books have answers, too many readers look at the answers and think they've understood the problems.

So if you could not make your first strategy work, perhaps you should try harder. The main point to realize is that you should use copy rather than uninitialized_copy to copy the elements that are to fill the erasure; then destroy the elements at the end separately.

arkoenig 340 Practically a Master Poster

Your code has an interesting strategy, but it has a few problems.

First, the C++ standard defines erase to work by copying elements from the part of the vector after the erasure on top of the elements being erased, then destroying the elements at the end of the original vector. It does this for several reasons.

One reason is that this strategy makes it unnecessary to have enough memory to contain two copies of the entire vector, which would otherwise be necessary if you were erasing, say, a single element. It also makes it unnecessary to copy the elements before the point of the erasure, which might be important if you are erasing only a few elements near the end of the vector.

Still, your strategy is an interesting one, and it has the advantage that if you are erasing a large part of the vector, you wind up using less memory after the smoke has cleared. So let's look at the code and see if there are any problems.

My first observation is that the parameters begin and end should be type iterator or const iterator& , not iterator& . As your code is written, it insists on accepting lvalues as arguments, and implicitly states its intention to modify those arguments--which you have no reason to want to do.

The next problem is on line 12, where the second argument to uninitialized_copy , begin-1 , should be begin . It is easy to see …

arkoenig 340 Practically a Master Poster

Can you show us what your copy constructors and assignment operators are for Vector3 and Quaternion?

arkoenig 340 Practically a Master Poster

When you apply sizeof to an object of type string , you get the amount of memory that needs to be allocated for an object of that type, exclusive of dynamic memory. This number has nothing to do with the number of characters in the string , so the results you get will have little if any connection to anything useful.

arkoenig 340 Practically a Master Poster

The gentlemen above me have done a great job & answered well. I'd just like to add that chars inside switches are in fact converted to their ASCII equivalent ints. :)

Not quite. A char is just an integer with (usually) severe constraints on its value. Operations that involve chars and other integral types have nothing to do with ASCII or any other encoding.

arkoenig 340 Practically a Master Poster

I have to say that I don't like either alternative, becuase there is a much simpler, cleaner one. There is a built-in function named getattr with the property that getattr(x, 'a') yields the value of x.a . Similarly, setattr(x, 'a', y) has the same effect as x.a = y .

arkoenig 340 Practically a Master Poster

Your struct node has a data member named info that you define but never use. What purpose does it serve?

arkoenig 340 Practically a Master Poster

You haven't actually asked a question; you've made a claim. As it happens, that claim is false, and it is false for a good reason.

Consider:

class Foo { /* something */ };

class Bar: public Foo {
public:
    void f(double);
};

// ...

void x()
{
    Bar b;
    b.f(0);       // Which function is called?
}

If C++ were to behave as you claim it does, you would not be able to answer this question, because the answer would depend on whether class Foo defined a member f that accepted an int argument. So whenever you derived a function from a class that someone else had written, you would have to know the name and argument types of every function in that base class, just in case you happened to define a function with the same name yourself.

Even worse: Suppose a newer version of the base class came along and defined a function that did not exist in a previous version? All of a sudden, you would find the meaning of your code changed.

So what C++ actually does is to say that a derived class is a new scope. Except for virtual functions, very name defined in a derived class hides the corresponding name from any base classes. Although this rule sometimes behaves in ways that seem surprising, in most cases it is safer than the alternative.

arkoenig 340 Practically a Master Poster

Is there a reason that you used "new" instead of using a vector?

(By the way, your example cannot work as you posted it, because

class

is a reserved word that you cannot use as a name for your own type)