473,378 Members | 1,104 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,378 software developers and data experts.

Arrays of dynamic objects and operator[]

Hi

I have three classes TDigest, THash and TSHA1.

//---------------------------------------------------------------------------
class TDigest
{
public:
// Constructors.
TDigest(int Count);
TDigest(const TDigest &Source);

// Destructors.
~TDigest();

// Operators.
TDigest& operator=(const TDigest &Source);
unsigned char& operator[](const int Index);

// Functions.
int Count();

private:
int count;
unsigned char *v,illegal;
};

TDigest has a variable length dynamic array, and is the return type of
THash::Digest() and its descendants. The operator[] provides
access to the individual bytes that make up the hash.

//---------------------------------------------------------------------------
class THash
{
public:
// Constructors.
THash();
THash(const THash &Source);

// Destructors.
virtual ~THash();

// Operators.
THash& operator=(const THash &Source);

// Functions.
virtual void Init(unsigned int Count);
virtual void Block(char* Block);
virtual TDigest Digest();

protected:
unsigned int count;
virtual void Process();
};

THash is the base class for implementing a family of hash algorithms.

//---------------------------------------------------------------------------
class TSHA1:public THash
{
public:
// Constructors.
TSHA1();
TSHA1(const TSHA1 &Source);

// Destructors.
~TSHA1();

// Operators.
TSHA1& operator=(const TSHA1 &Source);

// Functions.
void Init(unsigned int Count);
void Block(char* Block);
TDigest Digest();

protected:
unsigned int blocks,expand[80],work[5],hash[5],round[4];
void Process();
};

TSHA1 produces the SHA-1 hash for the supplied blocks of data.

My dilemma begins when trying to return the digest.

The following works, but has the overhead of temporaries with
associated constructor and destructor calls.

TDigest THash::Digest()
{
TDigest digest(20); // setup 160-bit digest.
int index = 0;
for...
for...
digest[index++] = ...
return digest;
}

What I would prefer to do is:
TDigest* THash::Digest()
{
TDigest digest = new TDigest(20); // setup 160-bit digest.
int index = 0;
for...
for...
digest[index++] = ...
return digest;
}

However, at the digest[index++] point, how does the compiler
distinguish between an array of TDigest objects, or the operator[] to
access a specific byte of the digest's internal array? In this case,
the compiler appears to assume that an array of objects has been
created (which seems odd to me since there was no "new TDigest[count]"
involved) and generates code to access the index-th digest object,
which does not exist beyond 0 (digest is digest[0]).

The following works:
digest[0][index++] = ...
but is non-intuitive. The non-intuitive problem persists since:
....
TDigest *result = sha.Digest();
for(int i = 0; i < result->Count(); i++)
{
... = result[0][i];
}

Unfortunately, references do not help either, since the compiler
errors:
"Attempting to return a reference to a local variable 'result'"

I had hoped that my Meyers' or Sutter's texts would shed some light on
this, but I am still in the dark.

Thanks in advance.

Andrew
Jul 19 '05 #1
3 3025
An***********@telkomsa.net wrote:
My dilemma begins when trying to return the digest. What I would prefer to do is:
TDigest* THash::Digest()
{
TDigest* digest = new TDigest(20); // setup 160-bit digest.
int index = 0;
for...
for...
digest[index++] = ...
return digest;
}

However, at the digest[index++] point, how does the compiler
distinguish between an array of TDigest objects, or the operator[] to
access a specific byte of the digest's internal array?


What's important here is how the compiler views digest. It is, first and
foremost, a pointer. That it's a pointer to a TDigest is not really
important to the compiler (in this scenario). For a TDigest object, it would
use operator[] as defined on TDigest, but for TDigest*, it uses the
operator[] as defined for pointers, which is memory indexing.

As you noted, one way to get at TDigest.operator[] is digest[0][index++],
but that's not really natural.

What you need to do is dereference the pointer before accessing operator[]:
(*digest)[index++]

It's not really elegant syntax, but it's necessary.

--
Unforgiven

"Most people make generalisations"
Freek de Jonge

Jul 19 '05 #2
On Thu, 2 Oct 2003 14:19:43 +0200, "Unforgiven"
<ja*******@hotmail.com> wrote:
An***********@telkomsa.net wrote:
My dilemma begins when trying to return the digest.

What I would prefer to do is:
TDigest* THash::Digest()
{
TDigest* digest = new TDigest(20); // setup 160-bit digest.
int index = 0;
for...
for...
digest[index++] = ...
return digest;
}

However, at the digest[index++] point, how does the compiler
distinguish between an array of TDigest objects, or the operator[] to
access a specific byte of the digest's internal array?


What's important here is how the compiler views digest. It is, first and
foremost, a pointer. That it's a pointer to a TDigest is not really
important to the compiler (in this scenario). For a TDigest object, it would
use operator[] as defined on TDigest, but for TDigest*, it uses the
operator[] as defined for pointers, which is memory indexing.

As you noted, one way to get at TDigest.operator[] is digest[0][index++],
but that's not really natural.

What you need to do is dereference the pointer before accessing operator[]:
(*digest)[index++]

It's not really elegant syntax, but it's necessary.


Thanks for the prompt reply!

I guess I must just accept the overhead of copy constructor and
destructor and use:

TDigest TSHA1::Digest()
{
TDigest result(20);
int pos = 0;
for...
for...
result[pos++] = ...
return result;
}

I did notice in the version below with dereferencing that the copy
constructor fires (on return), but no destructor!

TDigest& TSHA1::Digest()
{
TDigest *result = new TDigest(20);
int pos = 0;
for...
for...
(*result)[pos++] = ...
return *result;
}
....
TSHA1 sha;
....
TDigest digest = sha.Digest();

digest is copy constructed from *result, but *result is not deleted? A
memory leak?!

This brings one to the core issue:
When a class is the return type, how should it be constructed?

Just a "direct" object?

TDigest THash::Digest()
{
TDigest result(20);
....
return result;
}
Jul 19 '05 #3
> class TDigest
{
public:
...
unsigned char& operator[](const int Index);
...
}; My dilemma begins when trying to return the digest.

The following works, but has the overhead of temporaries with
associated constructor and destructor calls.

TDigest THash::Digest()
{
TDigest digest(20); // setup 160-bit digest.
int index = 0;
for...
for...
digest[index++] = ...
return digest;
}

What I would prefer to do is:
TDigest* THash::Digest()
{
TDigest digest = new TDigest(20); // setup 160-bit digest.
Illegal

TDigest *digest = new TDigest(20);
int index = 0;
for...
for...
digest[index++] = ...
return digest;
}

However, at the digest[index++] point, how does the compiler
distinguish between an array of TDigest objects, or the operator[] to
access a specific byte of the digest's internal array?


'digest' is a TDigest* and what you want is to access
TDigest::operator[](), no ?

(*digest)[index++] = ...
digest => TDigest*
(*digest) => TDigest
(*digest)[](x) => unsigned char&

Don't forget to delete the digest you got somewhere.
Jonathan
Jul 19 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

9
by: strotee76 | last post by:
What do I need to do to setTerm() for it to work properly? If you notice any other glaring issues, then please let me know. With this header file: ======================= #ifndef Polynomial_h...
21
by: Matteo Settenvini | last post by:
Ok, I'm quite a newbie, so this question may appear silly. I'm using g++ 3.3.x. I had been taught that an array isn't a lot different from a pointer (in fact you can use the pointer arithmetics to...
34
by: Christopher Benson-Manica | last post by:
If an array is sparse, say something like var foo=; foo=4; foo='baz'; foo='moo'; is there a way to iterate through the entire array? --
10
by: Ian Todd | last post by:
Hi, I am trying to read in a list of data from a file. Each line has a string in its first column. This is what i want to read. I could start by saying char to read in 1000 lines to the array( i...
60
by: Peter Olcott | last post by:
I need to know how to get the solution mentioned below to work. The solution is from gbayles Jan 29 2001, 12:50 pm, link is provided below: >...
4
by: learnfpga | last post by:
Here is a little code I wrote to add the numbers input by the user.....I was wondering if its possible to have the same functionality without using dynamic arrays.....just curious..... ...
2
by: Dr Dav | last post by:
Hello all, I'm a physicist whose rewriting a numerical simulation, previously written in IDL, in C with the goal reducing runtime. As you may imagine, my C programming skills are quite poor but I...
2
by: headware | last post by:
Do dynamic arrays declared using ReDim have to be freed? I assume that if it's an array of dynamically created objects (e.g. Scripting.Dictionary), each one of those objects will have to be set to...
127
by: sanjay.vasudevan | last post by:
Why are the following declarations invalid in C? int f(); int f(); It would be great if anyone could also explain the design decision for such a language restricton. Regards, Sanjay
1
by: CloudSolutions | last post by:
Introduction: For many beginners and individual users, requiring a credit card and email registration may pose a barrier when starting to use cloud servers. However, some cloud server providers now...
0
by: Faith0G | last post by:
I am starting a new it consulting business and it's been a while since I setup a new website. Is wordpress still the best web based software for hosting a 5 page website? The webpages will be...
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.