destructing error

M

michael.goossens

used code:

#include "Vecmath.h"
#include <iostream>

using namespace std;

int main(){
Vector v = Vector(4.0, 4.0, 2.0);
cout << "(" << v.x << ", " << v.y << ", " << v.z << ")" << endl;
cout << "length: " << v.Length() << endl;
cout << "normalizing ..." << endl;
Vector vn = Normalize(v);
cout << "normalized" << endl;
cout << "(" << vn.x << ", " << vn.y << ", " << vn.z << ")" << endl;
cout << "length: " << vn.Length() << endl;
vn.x = 1.f; vn.y = 0.f; vn.z = 0.f;
Vector *v2 = new Vector();
Vector *v3 = new Vector();
CoordinateSystem(vn, v2, v3);
cout << "(" << vn.x << ", " << vn.y << ", " << vn.z << ")" << endl;
cout << "(" << (*v2).x << ", " << (*v2).y << ", " << (*v2).z << ")"
<< endl;
cout << "(" << (*v3).x << ", " << (*v3).y << ", " << (*v3).z << ")"
<< endl;
delete v;
delete vn;
delete (*v2);
delete (*v3);

return 0;
}

The error occurs at the delete statements at the end and reads:
1>c:\users\michaël\documents\visual studio 2005\projects\renderwoman
\renderwoman\raytracer.cpp(22) : error C2440: 'delete' : cannot
convert from 'Vector' to 'void *'
1> No user-defined-conversion operator available that can
perform this conversion, or the operator cannot be called

same thing for line 22 to 25. Why does that happen? And deleting a
pointer should that be done by (*pointer) or just pointer ...
 
A

Alf P. Steinbach

* (e-mail address removed):
used code:

#include "Vecmath.h"
#include <iostream>

using namespace std;

int main(){
Vector v = Vector(4.0, 4.0, 2.0);
cout << "(" << v.x << ", " << v.y << ", " << v.z << ")" << endl;
cout << "length: " << v.Length() << endl;
cout << "normalizing ..." << endl;
Vector vn = Normalize(v);
cout << "normalized" << endl;
cout << "(" << vn.x << ", " << vn.y << ", " << vn.z << ")" << endl;
cout << "length: " << vn.Length() << endl;
vn.x = 1.f; vn.y = 0.f; vn.z = 0.f;
Vector *v2 = new Vector();
Vector *v3 = new Vector();
CoordinateSystem(vn, v2, v3);
cout << "(" << vn.x << ", " << vn.y << ", " << vn.z << ")" << endl;
cout << "(" << (*v2).x << ", " << (*v2).y << ", " << (*v2).z << ")"
<< endl;
cout << "(" << (*v3).x << ", " << (*v3).y << ", " << (*v3).z << ")"
<< endl;
delete v;
delete vn;
delete (*v2);
delete (*v3);

return 0;
}

The error occurs at the delete statements at the end and reads:
1>c:\users\michaël\documents\visual studio 2005\projects\renderwoman
\renderwoman\raytracer.cpp(22) : error C2440: 'delete' : cannot
convert from 'Vector' to 'void *'
1> No user-defined-conversion operator available that can
perform this conversion, or the operator cannot be called

same thing for line 22 to 25. Why does that happen?

Since v and vn have not been allocated by new, and are not pointers,
it's neither necessary nor possible to use delete.

Anyways, instead of explicit new and delete, which is darn difficult to
get right (matching every executed new with exactly one executed
delete), consider using smart pointers such as boost::shared_ptr, which
automate this.

And deleting a
pointer should that be done by (*pointer) or just pointer ...

delete applies to a pointer -- but see above.


Cheers, & hth.,

- Alf
 
M

michael.goossens

yep you are right:

//delete v;
//delete vn;
delete v2;
delete v3;

works :). I know its kind of stupid to delete everything manually but
its just a test since I never used destructors before, java
slutting ;).

BTW: Why isn't it possible to do:
Vector *v2;
Vector *v3;
CoordinateSystem(vn, v2, v3);

v2 and v3 being returned by reference:

inline void CoordinateSystem(const Vector &v1, Vector *v2, Vector *v3)
{
if(fabsf(v1.x) > fabsf(v1.y)){
// invLen is the inverse of the length of v1, it can be used later
as a multiplication, which is faster then divisions.
float invLen = 1.f / sqrtf(v1.x * v1.x + v1.z * v1.z);
*v2 = Vector(-v1.z * invLen, 0.f, v1.x * invLen);
} else {
float invLen = 1.f / sqrtf(v1.y * v1.y + v1.z*v1.z);
*v2 = Vector(0.f, -v1.z * invLen, -v1.y * invLen);
}
*v3 = Cross(v1, *v2);
}
 
A

Alf P. Steinbach

* (e-mail address removed):
yep you are right:

//delete v;
//delete vn;
delete v2;
delete v3;

works :). I know its kind of stupid to delete everything manually but
its just a test since I never used destructors before, java
slutting ;).

BTW: Why isn't it possible to do:
Vector *v2;
Vector *v3;
CoordinateSystem(vn, v2, v3);

v2 and v3 being returned by reference:

inline void CoordinateSystem(const Vector &v1, Vector *v2, Vector *v3)

You would have to do

inline void CoordinateSystem(
Vector const& v1, Vector*& v2, Vector*& v3
)

and assign pointers to the pointers (ahem) in the function body.

{
if(fabsf(v1.x) > fabsf(v1.y)){
// invLen is the inverse of the length of v1, it can be used later
as a multiplication, which is faster then divisions.
float invLen = 1.f / sqrtf(v1.x * v1.x + v1.z * v1.z);
*v2 = Vector(-v1.z * invLen, 0.f, v1.x * invLen);
} else {
float invLen = 1.f / sqrtf(v1.y * v1.y + v1.z*v1.z);
*v2 = Vector(0.f, -v1.z * invLen, -v1.y * invLen);
}
*v3 = Cross(v1, *v2);
}

Far better to code this without pointers, as (just code transformation)

inline double xzSquareLength( Vector const v )
{
return v.x*v.x + v.z*v.z;
}

inline double yzSquareLength( Vector const v )
{
return v.y*v.y + v.z*v.z;
}

inline Vector CoordinateSystem( Vector const& v )
{
if( abs( v1.x ) > abs( v1.y ) )
{
// invLen is the inverse of the length of v1, it can be used
// later as a multiplication, which may or may not be faster
// then divisions.
double const invLen = 1.f / sqrt( xzSquareLength( v1 ) );
return Vector( -v1.z * invLen, 0, v1.x * invLen );
}
else
{
double const invLen = 1.f / sqrt( yzSquareLength( v1 ) );
return Vector( 0, -v1.z * invLen, -v1.y * invLen );
}
}

then call as

Vector const v2 = CoordinateSystem( vn );
Vector const v3 = Cross( vn, v2 );

Perhaps also a name change CoordinateSystem -> projectedOntoXZorYZ.


Cheers, & hth.,

- Alf
 
G

Grizlyk

        Vector *v2 = new Vector();
        Vector *v3 = new Vector();
...
        delete (*v2);
        delete (*v3);

It is highly recommened to avoid naked pointers at least outside of
class scope, i mean, you can use the POD pointers as members of class,
because class have own ccor and dtor, but not as pointer in plain code
(a code, desined to do error handling, is one of some examples of
exception from the rule).

And even inside a class, any RAII wrapper (special class, desined to
replace POD pointers) can be better than naked pointer.

It is not so difficult even to write own wrapper to substitute auto
local block memory behavior.

wrapper<Vector> v2 = new Vector();
wrapper<Vector> v3 = new Vector();

You do not need to exclicit call "delete" here.

Maksim A. Polyanin
http://grizlyk1.narod.ru/cpp_new
 
J

James Kanze

(e-mail address removed) wrote:
It is highly recommened to avoid naked pointers at least
outside of class scope,

Bullshit. Most of the time, pointers outside of class scope are
only used for navigation, and naked pointers are the most
appropriate tool. The only time you'd generally want a smart
pointer with local scope is when creating an object---you'd
probably want something like std::auto_ptr to hold it until
whoever's finally responsible for it gained control. And even
then, the most usual case would involve creating entity objects
which manage their own lifetime; i.e. which will have "gained
control" by the time the constructor has finished.

Of course, in the example code, you really don't want pointers
at all.
 
G

Grizlyk

James said:
Bullshit.  Most of the time, pointers outside of class scope are
only used for navigation, and naked pointers are the most
appropriate tool.  

It is evidently, in the example we are speaking about naked pointers
used to hold value returned from "new", used as owners of memory,
rather than the pointers used to access.

C-style pointers sholud not be used as owners. If the pointer is a
member of a class, the class became owner, so we can use the pointer
to hold value from "new".

There is proposal to C++ improvement to explicit declare type of the
pointers

Vector heap *v2 = new heap Vector();

The proposal is a way to control by compiler the wrong usage of the
pointers inside the class-owner.
Of course, in the example code, you really don't want pointers
at all.

The Vector does not look like std::vector, so the Vector could be
allocated by new here.

Maksim A. Polyanin
http://grizlyk1.narod.ru/cpp_new
 
J

James Kanze

James Kanze wrote:
It is evidently, in the example we are speaking about naked pointers
used to hold value returned from "new", used as owners of memory,
rather than the pointers used to access.
C-style pointers sholud not be used as owners. If the pointer is a
member of a class, the class became owner, so we can use the pointer
to hold value from "new".

In this example, yes. Except that in this example, the error
isn't using raw pointers instead of smart pointers, the error is
using pointers to begin with, rather than local objects. The
recommendation: "It is highly recommened to avoid naked pointers
at least outside of class scope" is bullshit precisely because
there are very few cases where you should use a pointer outside
of class scope other than for navigation. In most cases (there
are exceptions), you're dealing with either entity objects (and
so only navigating) or you're dealing with values (in which
case, you shouldn't be using pointers at all).
The Vector does not look like std::vector, so the Vector could be
allocated by new here.

If the name is Vector, one can, I assume, that it has container
semantics. At any rate, it is a single object whose lifetime
corresponds exactly to that of a local object. In other words,
he should be using a local variable, and not allocating on the
heap at all.
 
G

Grizlyk

James said:
The recommendation: "It is highly recommened to avoid
naked pointers at least outside of class scope" is
bullshit precisely because there are very few cases
where you should use a pointer outside of class scope
other than for navigation.

Other than for access. Again, read with attention, we are speaking about
concrete pointers which holds memory address from "new". For the pointers
this is correct recomendation and idea of using of raw pointers as owners
of memory outside of class scope is wrong.

You have skipped

The sentence means, that without explicit declaration we can not be sure,
that any raw pointer will be used for access only, not as owner, for
example

Vector* ptr=class_name::get();

is ptr owner or what? But

//can be owner
Vector heap* ptr=class_name::get();

//can not be owner, accessor only
Vector auto* ptr=class_name::get();

It is not a best developed proposal, but is better than nothing.
If the name is Vector, one can, I assume, that it has container
semantics. At any rate, it is a single object whose lifetime
corresponds exactly to that of a local object.
he should be using a local variable, and not allocating on the
heap at all.

Yes, if auto memory can be used, auto memory must be used.

Maksim A. Polyanin
http://grizlyk1.narod.ru/cpp_new
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads


Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,007
Latest member
obedient dusk

Latest Threads

Top