C vs. C++

B

beggars.banquet

Hi everybody
No trolling here, but I just thought C++ was just object oriented C
but I was recently surprised to learn that C was much more used in
numerical, computational physics. So here's my question : why would C
be better for this kind of programming.
 
I

Ian Collins

Hi everybody
No trolling here, but I just thought C++ was just object oriented C
but I was recently surprised to learn that C was much more used in
numerical, computational physics. So here's my question : why would C
be better for this kind of programming.

Physicists tend know C and not C++?
 
W

Wolfgang Draxinger

Hi everybody
No trolling here, but I just thought C++ was just object
oriented C but I was recently surprised to learn that C was
much more used in numerical, computational physics. So here's
my question : why would C be better for this kind of
programming.

Computational physics is all about throughput. When using C++
you'll also use it's features like templates and use libraries
like STL and Boost. Those are all great if you don't have to
squeeze out the last bit of performance.

Here's a small experiment for you. Compile the following small
C++ snippet:

#include <vector>
#include <list>

typedef std::vector<std::list<int>> intlistvector;

int test()
{
intlistvector A;

// just some random code, so that the compiler
// doesn't optimize it away
for(int i = 0; i < 50; ++i) {
std::list<int> B;
for(int j = 0; j < 50; ++j) {
B.push_back(i*j);
}
A.push_back(B);
}
return A.end().end();
}


Then look at the amount of symbols created, compiling this
innocent looking thing and as a bonus look at the code path that
retrieves the value returned. It has about the same amount of
layers like an onion (well, not so much, but close).

The problem is not, that the code generated was inefficient. The
problem is, that it's difficult to analyze/profile in the
prospect of a super parallel computing plattform.

Plain C however doesn't suffer from that amount of "behind the
scenes created code", it's mostly exactly the code you write and
that's it.

The frontends to the number crunchers are done in a "convenience
language" (mostly). And there nowadays the dominating one is
Python.

Maybe someone writes a high performance numerical library for
parallel computing in C++, which will reduce the amount of
hidden code to a minimum with clearly laid out code paths, then
C++ may become more popular in the field.

However I think that functional languages (OCaml, Haskell, Clean)
will be more likely to gain popularity.

Wolfgang Draxinger
 
C

CBFalconer

No trolling here, but I just thought C++ was just object oriented
C but I was recently surprised to learn that C was much more used
in numerical, computational physics. So here's my question : why
would C be better for this kind of programming.

That depends on who is answering you. If it is me, I will say that
C is much closer to the actual machine, so you can write code that
is not lost in ever-increasing overhead of C++. C is much closer
to assembly language, but is nicely portable.
 
J

James Kuyper

Hi everybody
No trolling here, but I just thought C++ was just object oriented C
but I was recently surprised to learn that C was much more used in
numerical, computational physics. So here's my question : why would C
be better for this kind of programming.

In my experience, they actually prefer Fortran, but C99 has added some
new features that remove some of the advantages Fortran used to have
over C, from the point of view of physicists. Most importantly, C now
has direct language level support for complex math, include a bunch of
new math library functions that take complex arguments and return
complex values.

C99 has also added variable length arrays, which make it much easier to
deal with arrays of data, especially multi-dimensional arrays.

C99 has also added a bunch of math library functions that give better
control over the finicky details of floating point math than C90
allowed, such as nexatafter().

By the way, every new feature that makes C more attractive to
computational physicists has been roundly criticized by people who can't
imagine why any significant number of programmers would need complex
numbers, multidimensional arrays, or precise control over floating point
math.

None of these features are in the current C++ standard, though some of
them are slated to be in the next one. However, C99 hasn't been around
long enough for that fact to have had much influence; in fact, for the
most part, C99 hasn't quite arrived, yet.

I think that if C is indeed more popular than C++ among computational
physicists, it's probably because of a much older reason: C is a simpler
language than C++. Most of the advantages of C++ over C are of much
greater usefulness in GUI programming than they are in serious numerical
work.
 
W

William Hughes

Hi everybody
No trolling here,


At least none intended, but it is impossible
to post any comparison between two programming languages
(even at the level "I noticed that C has one charater
is its name and C++ has three) without inviting heated
discussion.
but I just thought C++ was just object oriented C

Do you enjoy waving red [1] flags in front of bulls?
A lot of people would claim otherwise (in my view correctly)?
but I was recently surprised to learn that C was much more used in
numerical, computational physics.

Possibly, although in my (limited) experience Fortran heavily
dominates both.
So here's my question : why would C be better
for this kind of programming.

Quite possible it isn't. The putative dominance of C can
be explained by a number of other mechanisms. One is just
that there may be more numerical programmers who know C.
There may be more legacy code in C. Very importantly, for very
high performance work the compiler is as or more important than
the language. It may well be that very good optimizing
compliers are available for C, but not C++.

C++ has a reputation of adding more code behind the scenes,
making it harder to see what the effect of code/code changes
is. This may contribute to the reluctance of some to use
C++ for high performance stuff.

I like a mixed mode in which problems are prepared in
a higher level language (I like Python) and a lower level
language (I like C) is used
for computationally intensive stuff (I do image processing,
It is not too much of a stretch to say the filter coefficients
are calculated in Python, and the filter applied in C).
In mixed mode programming I think C++ tends to get squeezed out,
as its best feature are needed for higher level work.
(Others disagree).

- William Hughes

[1] Yes, I know.
 
J

jameskuyper

James Kuyper wrote:
.....
... Most importantly, C now
has direct language level support for complex math, include a bunch of
new math library functions that take complex arguments and return
complex values.

That paragraph overstates my case, and was more nearly correct about C+
+1998 than about C++2003.

....
None of these features are in the current C++ standard, ...

That comment was more accurate with reference to the other features I
was talking about, than it was about complex math.

C++ does have support for complex math, though it's entirely at the
library level, rather than at the language level. Thanks to C++
features such as operator overloading and references, it's
syntactically nearly indistinguishable from language-level support. If
the library is implemented properly, and the compiler performs
sufficiently aggressive optimization, then it can have performance
comparable to that which could be more easily achieved by implementing
complex support at the language level. Also, the latest (2003) version
of the C++ standard adds a lot of functionality equivalent to the new
C99 math library functions. As a result, this point is much weaker
than it was as originally written.
 
T

Tomás Ó hÉilidhe

Hi everybody
No trolling here, but I just thought C++ was just object oriented C
but I was recently surprised to learn that C was much more used in
numerical, computational physics. So here's my question : why would C
be better for this kind of programming.


People have made arguments along the lines of using "std::vector" will
result in more bloated, slower code.

When you compare C and C++ and talk about using the C++ Standard
Library, you're not comparing the languages at all but merely
comparing the languages as they tend to be used by a lot of people.

There's nothing in the C++ Standard that says you have to use
std::vector instead of an array.

I, for one, program in C++ but I prefer procedural programming a lot
of the time. Plus I can't remember the last time I used "std::vector",
I use arrays instead.

C++ is C with more features added, and is inherently better. The
downside is that there's less compilers available. Sure, if you use
the C++ Standard Library to do stuff, you /might/ end up with less
efficient code, but you'd be surprised at how well written the C++
Standard Library tends to be.
 
J

jacob navia

Hi everybody
No trolling here, but I just thought C++ was just object oriented C
but I was recently surprised to learn that C was much more used in
numerical, computational physics. So here's my question : why would C
be better for this kind of programming.

EXHIBIT 1:
----------
template <typename T, typename T::value>

You think that both parameters are types isn't it?
After all, BOTH are "typenames".

Wrong.

Explain me why. Then you will understand why I do not really
like C++.

EXHIBIT 2:
---------
double const pi = 3.14159265359;
template <class T>
int f(T& x) { return x.convert<3>(pi); }

If T::convert is a member function template, the "x.convert" passes
pi to a specialization of convert<3>. But if it is a data member f
returns (x.convert < 3) > pi.

How do you disambiguate this?
Then you will understand why C++ is maybe a bit too complex for my
taste.
 
K

Kaz Kylheku

EXHIBIT 1:

I don't think this is valid syntax.
You think that both parameters are types isn't it?
After all, BOTH are "typenames".

C++ should have a better keyword for denoting template
parameters.

Really, does there even have to be a keyword? Enclosure in the
template parameter list ought to be enough.

template <T, T::value> {

}

When there is the lack of any specifier, the behavior should default to
that behavior which is currently denoted by "typename".

Abuse of keywords didn't start in C++.

This is simply the consequence of language design around reserved keywords.
Reserved keywords are troublesome because when you need a new one, you break
code. If you opt to reuse an old one, you wreck the language. A sagacious
programming language designer recognizes this problem, and therefore avoids
introducing the feature of reserved keywords.
Wrong.

Explain me why. Then you will understand why I do not really
like C++.

Keyword abuse started in C. What about adding "static" to objects that
are already in static storage, to denote internal linkage?
EXHIBIT 2:
---------
double const pi = 3.14159265359;
template <class T>
int f(T& x) { return x.convert<3>(pi); }

If T::convert is a member function template, the "x.convert" passes
pi to a specialization of convert<3>. But if it is a data member f
returns (x.convert < 3) > pi.

Syntax which depends on semantics in any way whatsoever is brain-damaged.

There should be no such feedback in the language processing pipeline. No
lexing decisions based on where you are in the grammar, no grammar decisions
based on semantics.

C has it too, though not as blatantly bad as this. foo(bar) is either a
function call, or a declaration of bar to be of type foo. It depends on
semantic information: how foo was declared.

Same thing: semantic information about an identifier determines which parse we
apply.

The only difference is that this may be considered a dime whereas in C++
it's more of a dollar.

Well, maybe that's just inflation between 1973 and 2003. :)
 
J

jacob navia

Kaz said:
I don't think this is valid syntax.


C++ should have a better keyword for denoting template
parameters.

Really, does there even have to be a keyword? Enclosure in the
template parameter list ought to be enough.

template <T, T::value> {

}

When there is the lack of any specifier, the behavior should default to
that behavior which is currently denoted by "typename".

There are two "specifiers": class, and typename. Class is somehow
misleading since the parameter can be any type, and not a class.

For instance vector said:
Abuse of keywords didn't start in C++.

Surely not but in C++ it has been taken to ridiculous extremes...

This is simply the consequence of language design around reserved keywords.
Reserved keywords are troublesome because when you need a new one, you break
code. If you opt to reuse an old one, you wreck the language. A sagacious
programming language designer recognizes this problem, and therefore avoids
introducing the feature of reserved keywords.


Keyword abuse started in C. What about adding "static" to objects that
are already in static storage, to denote internal linkage?

The solution for the riddle above is

return x.template convert<3>(pi);

Interesting. You are an experienced C++ programmer, and you did not know
this. It may be because nobody in the world (except Stroustrup)
has mastered the WHOLE language.
 
C

CBFalconer

Tomás Ó hÉilidhe said:
.... snip ...

C++ is C with more features added, and is inherently better. The
downside is that there's less compilers available. Sure, if you use
the C++ Standard Library to do stuff, you /might/ end up with less
efficient code, but you'd be surprised at how well written the C++
Standard Library tends to be.

For some peculiar definitions of 'better'.
 
T

Tomás Ó hÉilidhe

For some peculiar definitions of 'better'. <and nothing more>


There is /nothing/ that can be achieved more elegantly or more
efficiently in C, than it can be achieved in C++. Nothing. If you
think there's something then I'll listen intently.

Meanwhile there's loads of stuff that can be achieved more
elegantly in C++ than can be achieved in C.

The only reason at all to use a C compiler on code written today
in 2009 is the inavailability of a C++ compiler. Either that or you
like using "class" as an identifier. (By the way I don't doubt that
many people make such an argument regarding the amount of reserved
keywords in C++).

The distinction between a C programmer and a C++ programmer today
in 2009 is more cultural than factual. I, for instance, started out
programming in C++; I learned all the elaborate features of C++ inside
out... and then finally years later I ended up using C to do an
embedded systems project for college. I was using a C compiler because
there was no C++ compiler for the 8-Bit microcontroller I was using.
When I want to store a number of items in memory, I'll do the
following:

WhateverType my_array[whatever_number];

WhateverType *p = my_array;
WhateverType const *const pend = my_array + whatever_number;

do *p++ = GetDataFromSomewhere();
while (pend != p);

Regardless of whether I'm using a C compiler or a C++ compiler, this
is how I'll do it.

A more cultured C++ programmer would respond to my code with, "No,
that's C, this is how it's done in C++:"

std::vector<WhatEverType> blah blah blah

Regardless of how ingrained and how prevalent this C++ culture is, it
doesn't have any effect on the language itself. The C++ Language is
defined by the C++ Standard, and the C++ Standard mentions arrays as
well as std::vector. Specifically it does /not/ mention anything along
the lines of "arrays are considered deprecated and will be removed
from future editions of this standard".

The C++ programming language is a superset of the C programming
language. C++ can do everything C can do, and more. Therefore, it is
inherently better. (It's a different story for compiler implementors,
but I'm talking about programmers here).

Nowadays, unless I'm writing a program that would see great benefit
from using stuff like classes and templates, I usually write the code
in C so that it will be compilable on the greatest number of systems
possible (because you can be absolutely certain that the list of
platforms that have C compilers is a superset of the list of platforms
that have C++ compilers).

But again, C++ is C with more features added, and so is inherently
better. Sort of like how the Supersoaker 6000 is inherently better
than the Supersoaker 5000. It doesn't mean the Supersoaker 5000 has no
use, I mean you might decide to bring it into school because it's
smaller and less conspicuous in your schoolbag, but in its role as a
water gun, the Supersoaker 6000 is inherently better. But if you've
got a small schoolbag then fair enough use the 5000.
 
W

William Hughes

There is /nothing/ that can be achieved more elegantly or more
efficiently in C, than it can be achieved in C++.


This follows from the fact that C++ is very close to a superset
of C. However, as you note, this does not mean that the way
things are usually done in C is not more elegant or more
efficient that the way things are usually done in C++.

Nothing. If you
think there's something then I'll listen intently.

Meanwhile there's loads of stuff that can be achieved more
elegantly in C++ than can be achieved in C.

The only reason at all to use a C compiler on code written today
in 2009 is the inavailability of a C++ compiler.

Or the suboptimality of a C++ compiler. As noted, for high
performance computing the quality of the compiler is often
paramount. As a rough rule of thumb, the more complex the language
the harder it is to optimize.
Either that or you
like using "class" as an identifier. (By the way I don't doubt that
many people make such an argument regarding the amount of reserved
keywords in C++).

The distinction between a C programmer and a C++ programmer today
in 2009 is more cultural than factual. I, for instance, started out
programming in C++; I learned all the elaborate features of C++ inside
out... and then finally years later I ended up using C to do an
embedded systems project for college. I was using a C compiler because
there was no C++ compiler for the 8-Bit microcontroller I was using.
When I want to store a number of items in memory, I'll do the
following:

WhateverType my_array[whatever_number];

WhateverType *p = my_array;
WhateverType const *const pend = my_array + whatever_number;

do *p++ = GetDataFromSomewhere();
while (pend != p);

Regardless of whether I'm using a C compiler or a C++ compiler, this
is how I'll do it.

A more cultured C++ programmer would respond to my code with, "No,
that's C, this is how it's done in C++:"

std::vector<WhatEverType> blah blah blah

Regardless of how ingrained and how prevalent this C++ culture is, it
doesn't have any effect on the language itself. The C++ Language is
defined by the C++ Standard, and the C++ Standard mentions arrays as
well as std::vector. Specifically it does /not/ mention anything along
the lines of "arrays are considered deprecated and will be removed
from future editions of this standard".

The C++ programming language is a superset of the C programming
language. C++ can do everything C can do, and more. Therefore, it is
inherently better. (It's a different story for compiler implementors,
but I'm talking about programmers here).

Even for programmers it does not follow that a superset of a language
is inherently better. Ease of problem expressibility is only one
consideration,
complexity is another (there are of course others).
Your point is of even less true
for high performance computing where the complier is central.
Nowadays, unless I'm writing a program that would see great benefit
from using stuff like classes and templates, I usually write the code
in C so that it will be compilable on the greatest number of systems
possible (because you can be absolutely certain that the list of
platforms that have C compilers is a superset of the list of platforms
that have C++ compilers).

But again, C++ is C with more features added, and so is inherently
better.

Yep, more features equates to better. Ever considered a
career as a PHB?
Sort of like how the Supersoaker 6000 is inherently better
than the Supersoaker 5000. It doesn't mean the Supersoaker 5000 has no
use, I mean you might decide to bring it into school because it's
smaller and less conspicuous in your schoolbag, but in its role as a
water gun, the Supersoaker 6000 is inherently better. But if you've
got a small schoolbag then fair enough use the 5000.

If one of the requirements is that the water gun you pick fits
into your schoolbag then the Supersoker 6000 is not better it
is useless.

- William Hughes
 
T

Tomás Ó hÉilidhe

Or the suboptimality of a C++ compiler. As noted, for high
performance computing the quality of the compiler is often
paramount. As a rough rule of thumb, the more complex the language
the harder it is to optimize.


I don't see any reason why the optimisation can't take place /
after/ the higher-level stuff like virtual functions has been reduced
to V-Tables and function pointers. By the way, when it comes to GCC
and G++, I think their common subset of features have equivalent
optimisation.

Even for programmers it does not follow that a superset of a language
is inherently better. Ease of problem expressibility is only one
consideration,
complexity is another (there are of course others).
Your point is of even less true
for high performance computing where the complier is central.


OK fair enough that's another reason to use C, i.e. if there's a
lightning fast compiler for it for which there is no C++ equivalent.

Yep, more features equates to better. Ever considered a
career as a PHB?


The more features the better, so long as they're tucked away. I bought
a Nokia mobile phone about a month or so ago. I looked for the most
basic phone I could find, I didn't want a camera, or MP3 player, or
even picture messages. I want the phone interface to be minimalistic,
I hate looking at menus filled with all sorts of shite. I like to be
able to browse the entire menu of my phone in about 5 minutes. Plus I
bought a Nokia coz they last forever.

But I don't mind features if they're tucked away. Take Linux for
instance, it has all sorts of goodies that people don't know about,
and they don't get in the way. Try type in "cal" at the command line.
But then one time I installed Ubuntu, and I hated it coz there was too
many features in your face.

The thing about the extra features of C++ is that you can be oblivious
to them. Take a C programmer and just tell him to do a handful of
stuff such as not use "class" as an identifier, and they're good to
go. They can use their C++ compiler as a C compiler.

If one of the requirements is that the water gun you pick fits
into your schoolbag then the Supersoker 6000 is not better it
is useless.


Yes I realise this. So here's how I'd explain it:

The Supersoaker 6000 is the better water gun unless you have
extraneous requirements, such as needing to fit it in your school bag.

But without getting into extraneous requirements, I think it's right
to say that the Supersoaker 6000 is better (it has three separate
water jet streams instead of two).
 
K

Keith Thompson

Tomás Ó hÉilidhe said:
There is /nothing/ that can be achieved more elegantly or more
efficiently in C, than it can be achieved in C++. Nothing. If you
think there's something then I'll listen intently.

Meanwhile there's loads of stuff that can be achieved more
elegantly in C++ than can be achieved in C.

Perhaps. I'll note that most of the features that were added to C99
have not yet been added to the C++ standard, but that's a temporary
situation.

(C's support for non-prototyped functions might let you do some things
in C that would be less convenient in C++, but I'm not going to take
the time to construct an example; it's not something I'd take
advantage of anyway.)
The only reason at all to use a C compiler on code written today
in 2009 is the inavailability of a C++ compiler. Either that or you
like using "class" as an identifier. (By the way I don't doubt that
many people make such an argument regarding the amount of reserved
keywords in C++).

No, that's not the only reason. If I want to write C code, I need to
use a C compiler; that's the only way I can be sure that I don't
accidentally use some C++-specific feature. It's not just about
keywords. I can't use a C++ compiler to check that my code is
portable C.

For example, suppose I unthinkingly write something like:

int x = 42;
double y = double(x);

That's a valid C++ conversion, but a syntax error in C. A C++
compiler won't tell me about my mistake.

[...]
The C++ programming language is a superset of the C programming
language. C++ can do everything C can do, and more. Therefore, it is
inherently better. (It's a different story for compiler implementors,
but I'm talking about programmers here).

We all know that this isn't strictly true; it's easy to write valid C
code that's not valid C++ code, or that is valid C++ code with
different behavior. But your point, I think, is that C++ is
functionally, not literally, a superset of C, and that's nearly
correct (apart from the C99 issue I mentioned above).

[...]
But again, C++ is C with more features added, and so is inherently
better. Sort of like how the Supersoaker 6000 is inherently better
than the Supersoaker 5000. It doesn't mean the Supersoaker 5000 has no
use, I mean you might decide to bring it into school because it's
smaller and less conspicuous in your schoolbag, but in its role as a
water gun, the Supersoaker 6000 is inherently better. But if you've
got a small schoolbag then fair enough use the 5000.

The Supersoaker 5000's small size is a feature that the Supersoaker
6000 lacks.
 
T

Tomás Ó hÉilidhe

Tomás Ó hÉilidhe <[email protected]> writes:
(C's support for non-prototyped functions might let you do some things
in C that would be less convenient in C++, but I'm not going to take
the time to construct an example; it's not something I'd take
advantage of anyway.)


Implicit declarations are the devil. Even back when I was 11 years old
using Visual Basic I did "Option Explicit" to make sure I had to
declare everything before using it.

Anyway, to summarise the situation might be as follows:

C++ is a superset of C. C compilers are common as milk, whereas C+
+ compilers are about as common as chocolate milk. If a shop has
chocolate milk then you can be sure it also has normal milk. If a shop
has both chocolate milk and normal milk, then it's possible that the
normal milk is nice but the chocolate milk is yucky. It's harder to
find good chocolate milk than it is to find good normal milk. Some
people like the new features of C++, others don't. You're not obliged
to use the new features. The new features /can/ be a hindrance, in
terms of:
a) having more keywords and thus you're restricted in your use of
identifiers
b) mistakenly using a new feature you didn't know about (I don't
know how well this washes)

For what it's worth, if I knew that every platform had a C++ compiler,
I'd start using a C++ compiler for all my projects, even if I was
using templates and classes and stuff. I'd replace "printf" with
"cout", all that jazz.
 
A

Antoninus Twink


There is /nothing/ that can be achieved more elegantly or more
efficiently in C, than it can be achieved in C++. Nothing.

You have to bear in mind:

1) that CBF is a pure troll, best *plonked*

2) that for the fundamentalists here, a piece of code that is valid and
semantically identical in both C and C++
*is C++ and not C* if you compile it with a C++ compiler, and
*is C and not C++* if you compile it with a C compiler.

Idiotic word games? Of course - would you expect anything else?
 
K

Keith Thompson

Tomás Ó hÉilidhe said:
Yes I realise this. So here's how I'd explain it:

The Supersoaker 6000 is the better water gun unless you have
extraneous requirements, such as needing to fit it in your school bag.

But without getting into extraneous requirements, I think it's right
to say that the Supersoaker 6000 is better (it has three separate
water jet streams instead of two).

That works fine if you get to define which requirements are
"extraneous".
 
K

Keith Thompson

Tomás Ó hÉilidhe said:
Implicit declarations are the devil. Even back when I was 11 years old
using Visual Basic I did "Option Explicit" to make sure I had to
declare everything before using it.

I wasn't talking about implicit declarations, I was talking about
non-prototype function declarations.

For example, a given C function might be declared either as
double foo(double x, double y);
or as
double foo();
The latter is illegal in C++, if I recall correctly. In C, a pointer
of type ``double (*p)()'' can point to any non-variadic function.

I can't actually think of anything you can do with this that you can't
do without it (using explicit conversions), but I mention it for
completeness.
Anyway, to summarise the situation might be as follows:

C++ is a superset of C.

I know what you mean, but communication would be enhanced if you'd
avoid making that statement without qualification. I explained in my
previous followup several ways in which C++ is *not* a superset of C.

[...]
The new features /can/ be a hindrance, in terms of:
a) having more keywords and thus you're restricted in your use of
identifiers
b) mistakenly using a new feature you didn't know about (I don't
know how well this washes)

One of the most important jobs of a compiler is to diagnose errors;
it's nearly as important as handling legal code correctly. A C++
compiler cannot be expected to diagnose errors in C code.
For what it's worth, if I knew that every platform had a C++ compiler,
I'd start using a C++ compiler for all my projects, even if I was
using templates and classes and stuff. I'd replace "printf" with
"cout", all that jazz.

So you like C++ better than you like C. That's fine. But I think
your conclusion that C++ is unambiguously better than C is
overreaching. And I don't this discussion will ever reach any useful
conclusions, so I'm going to drop out unless something unexpected pops
up.
 

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

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,582
Members
45,070
Latest member
BiogenixGummies

Latest Threads

Top