LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 11-23-2009, 04:43 PM   #1
jmite
Member
 
Registered: Jun 2008
Distribution: Ubuntu
Posts: 266

Rep: Reputation: 36
Refer to object without name (with array reference)...is this valid?


Does anybody know if someting like this is valid in C++?
This assumes that class Foo has already been defined.
Code:
int size;
cin >> size;
Foo theArray[size];

for (int i=0; i<size; i++){
     Foo theArray[i] = new Foo;
}
I'm still pretty fresh when it comes to pointers, references, etc.

Last edited by jmite; 11-23-2009 at 04:45 PM. Reason: had an error in the demo code...
 
Old 11-23-2009, 04:59 PM   #2
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by jmite View Post
Does anybody know if someting like this is valid in C++?
This assumes that class Foo has already been defined.
Code:
int size;
cin >> size;
Foo theArray[size];

for (int i=0; i<size; i++){
     Foo theArray[i] = new Foo;
}
I'm still pretty fresh when it comes to pointers, references, etc.
I think in C++ array size should be a constant, not a variable - the same way as in "C".
 
Old 11-23-2009, 05:20 PM   #3
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by jmite View Post
Foo theArray[size];
That declares an array whose size is not known until run time.

I'm not certain what the C++ standard says about that. But I think it says you can't do that.

When I've tried that, it has worked. I think it may be an extension to the language generally supported by compilers.

Quote:
Foo theArray[i] = new Foo;
That is quite a bit less plausible.

It declares another array of the same name (that is not a problem because it is in an inner scope).

It obviously was intended to refer to an element of the first declaration, so the code is certainly wrong.

I've never tested the variable length local array feature inside a loop where the compiler would be unable to trivially manage the stack trick for allocating it. I don't know whether that makes a difference.

But the worst aspect is the initial value. new Foo generates a pointer to an object of type Foo. That is normally not a reasonable initializer in this context.

The meaning (if there is one) of this code is far enough from the intended meaning, I don't think I can guess the intended meaning. Maybe you should tell us what you want the code to do.

Last edited by johnsfine; 11-23-2009 at 05:26 PM.
 
Old 11-23-2009, 06:18 PM   #4
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by johnsfine View Post
That declares an array whose size is not known until run time.

I'm not certain what the C++ standard says about that. But I think it says you can't do that.

When I've tried that, it has worked. I think it may be an extension to the language generally supported by compilers.



That is quite a bit less plausible.

It declares another array of the same name (that is not a problem because it is in an inner scope).

It obviously was intended to refer to an element of the first declaration, so the code is certainly wrong.

I've never tested the variable length local array feature inside a loop where the compiler would be unable to trivially manage the stack trick for allocating it. I don't know whether that makes a difference.

But the worst aspect is the initial value. new Foo generates a pointer to an object of type Foo. That is normally not a reasonable initializer in this context.

The meaning (if there is one) of this code is far enough from the intended meaning, I don't think I can guess the intended meaning. Maybe you should tell us what you want the code to do.
Well, if array is created at runtime, it's allocated, And allocation can fail, so the allocation result should be checked for not being NULL, which makes it look like traditional 'malloc' or 'new'.

Is my understanding correct ?
 
Old 11-23-2009, 06:32 PM   #5
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Quote:
Originally Posted by johnsfine View Post
I'm not certain what the C++ standard says about that. But I think it says you can't do that.

When I've tried that, it has worked. I think it may be an extension to the language generally supported by compilers.
I'm almost certain this is a gcc extension; it shouldn't compile. When in doubt, try it out.

To OP: You're on the right track as far as some objectives; you just need an array of pointers, not an array of objects, if you're going to use new like that. But normally one would just use an array of objects (like you've created,) which are already constructed unless they're "plain old data" (e.g. pointers, built-in numerical types.) Creating an array of pointers is most often used when you want an array of polymorphic objects, but even then containers are more often used.

Because you use input to determine the size, you're better off using std::vector and resizing it once the input comes. You should also check to make sure the value is > 0; keeping track of things like that becomes extremely important. Here is a good STL API reference.

If you're interested in exploring the dynamic allocation of it, try something like this:
Code:
int size;
cin >> size;
Foo *theArray = new Foo[size];

//...

delete[] theArray;
Think of delete as a trap set at all the exits to capture all escaping memory. If you allocate memory in a certain scope, make sure it's accounted for at all exits, e.g. return statements, loop exits, end of if/then statements (if applicable.) If you were to create an array of pointers (Foo *theArray[]) and you filled it with new objects (theArray[i] = new Foo) you'd have to go and delete each one exactly as you allocated them. You'd also have to make sure the empty elements were set to NULL; therefore, arrays of pointers are often a nightmare.

Although most tutorials dump all of namespace std into the global scope, namespaces are there for a reason; therefore, you should get in the habit of fully-qualifying your classes and functions (e.g. std::cin.)
Kevin Barry

Last edited by ta0kira; 11-23-2009 at 06:43 PM.
 
Old 11-23-2009, 06:35 PM   #6
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
well, it works.
the compiler doesn't complain.
it works in C also.

AFAIK this is highly illegal - in C at least.

Code:
    int size;
    scanf("%d", &size);
    pthread_t  workers[size];
but it works.
I must admit I'm surprised.
it's not what I learnt from K&R.
 
Old 11-23-2009, 06:48 PM   #7
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
apparently in C99 it's valid!

excellent!

well good.

fab.

how useful is that?
cheers OP.

Last edited by bigearsbilly; 11-23-2009 at 06:49 PM.
 
Old 11-23-2009, 08:37 PM   #8
jmite
Member
 
Registered: Jun 2008
Distribution: Ubuntu
Posts: 266

Original Poster
Rep: Reputation: 36
Okay, so it's looking like vectors will be better in the long run... I'll look up the syntax for those and how to use them...

But in terms of the objects, the idea is that I don't know how many to declare, so I can't name them all. How do I reference them only in terms of their position within the vector?
 
Old 11-23-2009, 09:18 PM   #9
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by jmite View Post
it's looking like vectors will be better in the long run.
Vectors are usually better in cases where the element count of an array isn't know at compile time. With a vector, you don't even need to know the element count when you define the vector. You can change it later.

This thread already discussed the C99 feature of local (on the stack) arrays with sizes not known until run time. They work at least sometimes in some compilers in C and C++. But if the standard says it is wrong, they are probably best to avoid.

You can also use pointers with new and delete[] to correctly allocate arrays whose sizes are known when defined but not known at compile time. But that tends to be more difficult and less flexible than using vectors.

Quote:
I'll look up the syntax for those and how to use them.
If you know the size when you define it
Code:
std::vector<Foo> theArray(size);
If you don't know the size when you define it
Code:
std::vector<Foo> theArray;
Later
Code:
theArray.resize(size);
There are lots of other methods available, but you could use a vector with just the above plus basic element access.

Quote:
How do I reference them only in terms of their position within the vector?
You had that almost correct in your first post theArray[i] is used to access the element at position i in an array or a vector named theArray.

You do not re specify the datatype when accessing an element that way. The compiler knows the datatype. theArray[i] references that element of a previously declared array or vector, but Foo theArray[i] declared a new array of i elements, each of which is of type Foo.

But you also need to know what can reasonably do with a reference to an element of an array or vector.
Code:
theArray[i] = new Foo;
was not a reasonable assignment because theArray[i] is a reference to a Foo but new Foo produces a pointer to a Foo.

When you set the size of a vector of Foo, all the objects in the vector are initialized by copying a default value. Depending on how Foo was defined, similar may be true for an array of Foo (all elements initialized by the default constructor as soon as the array is defined). So you might not even need that loop that seemed to be intended to set all the objects in the array to default initial value.

If you do need to set or reset an element to a copy of the value created by the default constructor, the syntax is
Code:
theArray[i] = Foo();

Last edited by johnsfine; 11-23-2009 at 09:27 PM.
 
Old 11-23-2009, 10:14 PM   #10
jmite
Member
 
Registered: Jun 2008
Distribution: Ubuntu
Posts: 266

Original Poster
Rep: Reputation: 36
Perfect@ Thanks so much! That's exactly what I'm looking for.

One last question. How would I pass a vector as a parameter to a function. ie, if the vector was theArray, would I just do function(theArray)? In C++, are they passed by value, or by reference?

Thanks!
 
Old 11-23-2009, 11:42 PM   #11
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Everything in C is passed by value, whether that be an object or a pointer to one. In C++, references are a shortcut for passing using a pointer which allows you to avoid having to dereference it. If you're trying to pass an array, it's handled using a pointer to its first element. It all gets complicated after that: unlike in Java, you can arbitrarily nest pointers to the effect of "he said that she said that I said that this is the object," the last of which may be a reference (denoted by & instead of *.) It's probably best to stick with one or two levels of pointer-ing at this point.
Kevin Barry
 
Old 11-24-2009, 05:49 AM   #12
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
it depends,

you can do it like explicitly this: (e.g. a routine called dump)

Code:
void dump(vector<string> & v)
{
  // etc...
}
 
Old 11-24-2009, 05:51 AM   #13
bigearsbilly
Senior Member
 
Registered: Mar 2004
Location: england
Distribution: Mint, Armbian, NetBSD, Puppy, Raspbian
Posts: 3,515

Rep: Reputation: 239Reputation: 239Reputation: 239
or even better you can template it.
for instance this implementation of dump will accept
a list vector or deque

Code:
#include <iostream>
#include <string>
#include <vector>
#include <deque>
#include <list>

using namespace std;

template<typename T>
void dump(T & v)
{
    typename T::iterator p;
    for(p=v.begin(); p != v.end();p++) {
            cout << "got:" << *p << endl;
        }

}

int main ()
{

    string s;
    //vector<string> v;
    //deque<string> v;
    list<string> v;

    while (cin >> s) {

        v.push_back(s);
    }
    dump(v);
}
 
Old 11-24-2009, 08:33 AM   #14
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197Reputation: 1197
Quote:
Originally Posted by jmite View Post
How would I pass a vector as a parameter to a function.
Usually by reference. That is more efficient than passing by value and it allows the function to modify the contents (or even size) of the vector.

Quote:
In C++, are they passed by value, or by reference?
C++ passes by value unless the function declaration tells it to pass by reference.
Code:
typedef std::vector<Foo> myVector;  // Using a typedef is cleaner than using std::vector<Foo> everywhere you need the type

void myFunction( myVector& passedVector ); // The & used that way means pass by reference

int main( int argc, char** argv ) {
   ...
   myVector theVector(size);  // Define the vector and its size
   ...
   myFunction( theVector );  // The calling syntax for pass by reference is identical to pass by value
   ...
}

void myFunction( myVector& passedVector )
{
   ...
   ... passedVector[i] ... // The syntax inside the function is the same as for pass by value
   ...
}
At the places where you call a function, pass by reference looks the same as pass by value.

Inside the function where you use or modify the passed object the syntax is the same for pass by reference vs. pass by value. But the meaning is different. In pass by value, you are using or modifying a copy that ceases to exist when the function exits. In pass by reference, you are using or modifying the original.

The only syntax difference is the & added to the typename of the passed object in the argument list both where you declare the function and where you define the function.

Last edited by johnsfine; 11-24-2009 at 08:40 AM.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
tough (to me) c++ questions about pointer to class object reference and more parv Programming 6 01-11-2008 09:26 PM
Object array length ArcLinux Programming 2 11-04-2006 08:43 AM
How do I pass a C++ object reference to GTK+ callbacks??? paulsm4 Programming 1 12-14-2005 03:32 PM
Object Reference problem in Java servlets Hockeyfan Programming 1 06-16-2005 01:36 AM
returning a reference to Object C++ chens_83 Programming 3 10-10-2003 09:16 PM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 03:20 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration