Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
NotShadowStar
Sep 20, 2000

quote:

What happens if you do this?

quote:

Use of possibly unassigned field 'Baz'

Which is completely true. I would have expected a NullReferenceError but that'll do.

Adbot
ADBOT LOVES YOU

Sedro
Dec 31, 2008

thelightguy posted:

I'm having a hard time figuring out where that might be in any way useful.

Should declaring any value type initialize it to its default value? Why are structs a special case?

Imagine if C++ behaved like C# value types except the compiler didn't bother you about uninitialized variables. That seems pretty in line with the rest of the language.

floWenoL
Oct 23, 2002

Dicky B posted:

Non c++ programmers talking about c++ :allears:

This level of ignorance about C++ is yet another coding horror.

Zombywuf
Mar 29, 2008

References being invisible and impossible to manipulate separately to values is the real horror.

I especially love the "safe" language fans arguing for uninitialised variables being a good thing.

corgski
Feb 6, 2007

Silly goose, you're here forever.

Sedro posted:

Should declaring any value type initialize it to its default value?

Yes (that default value being null in most cases.) I don't see any practical usage for an uninitialized variable.

Jabor
Jul 16, 2010

#1 Loser at SpaceChem

thelightguy posted:

Yes (that default value being null in most cases.) I don't see any practical usage for an uninitialized variable.

It's similar to how the compiler requires you to declare variables before using them, even when it's capable of inferring the type for you.

There are uses for a partially-initialized struct - you might only ever use some of the fields, for example. And then the compiler checks for you and makes sure you never use one of the fields you haven't initialized.

Zombywuf
Mar 29, 2008

thelightguy posted:

Yes (that default value being null in most cases.) I don't see any practical usage for an uninitialized variable.

null is not a valid value of struct { int foo; }.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
This thread has gone off the loving wall. Next people are going to start flipping out when they learn that the destructor is called at the end of a variable's scope.

nielsm
Jun 1, 2009



Yeah. C++ is insanely complex. It takes lots of effort to learn all the details. When you know them, it's a really great language. The only true fault of C++ is that it's hard to learn.

Let's rather discuss how retarded it is that "good old" C allows you to declare a function with an unknown argument list and then just call it with whatever parameters.

tef
May 30, 2004

-> some l-system crap ->

nielsm posted:

Yeah. C++ is insanely complex. It takes lots of effort to learn all the details. When you know them, it's a really great language. The only true fault of C++ is that it's hard to learn.

Where other languages eschew complexity C++ embraces it with open arms and its tongue wagging. Being 'hard to learn is a symptom, along with the other symptoms of being hard to implement, hard to debug, etc.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



thelightguy posted:

I'm having a hard time figuring out where that might be in any way useful.

If you need access to an object in the finally block of a try, you have to declare it outside of the try, but you do not have to instantiate it outside the try.

Hughlander
May 11, 2005

From 2 fast moving pages ago...

Internet Janitor posted:

I'm brushing up on C and networking stuff. The quality of example code online is great:

code:
printsin( sin, m1, m2 )
struct sockaddr_in *sin;
char *m1, *m2;
{
    struct hostent *gethostbyaddr(), *h;

    printf ("%s %s:\n", m1, m2);
    printf ("  family %d addr %x port %d\n", sin -> sin_family,
	    sin -> sin_addr.s_addr, sin -> sin_port);
}
There are just layers to this. Does anybody still intentionally write method signatures like that? What is the deal with that hostent pointer?

It's networking code. It's probably source compatible with an embed chip running some clusterfuck of a Pre-ANSI C compiler and that's the only thing known to work on the 19 platforms it has to support.

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

Munkeymon posted:

If you need access to an object in the finally block of a try, you have to declare it outside of the try, but you do not have to instantiate it outside the try.
An even simpler example is declaring a base type or interface and then instantiating it two different ways in an if/else
code:
IAnimal animal;
if (wantCat)
{
  animal = new Cat();
}
else
{
  animal = new Dog();
}
animal.MakeNoise();

baquerd
Jul 2, 2007

by FactsAreUseless

Munkeymon posted:

If you need access to an object in the finally block of a try, you have to declare it outside of the try, but you do not have to instantiate it outside the try.

Or suppose you want a placeholder member variable at the object level that will be defined in constructor arguments:

code:
class foo {
  final Object butts;
  foo(Object butts) {
     this.butts = butts;
  }
Why would you want an instantiated butts at declaration? Hint: you wouldn't and it would actually break this.

There are lots of uses:

code:
void doStuff(MySuperClass goon) {
  MySuperClass localGoon;
  if (goon instanceof MyChildClass) {
    localGoon = new MyChildClass(goon, goon.getChildField());
  } else {
     localGoon = new MySuperClass(goon);
  }
  localGoon.modifyShit();
  localGoon.doStuff()
}
Edit: beaten by a loving Cat.

Zombywuf
Mar 29, 2008

baquerd posted:

Or suppose you want a placeholder member variable at the object level that will be defined in constructor arguments:

code:
class foo {
  final Object butts;
  foo(Object butts) {
     this.butts = butts;
  }
Why would you want an instantiated butts at declaration? Hint: you wouldn't and it would actually break this.
code:
foo::foo(Object b)
  : butts(b)
{}

quote:

There are lots of uses:

code:
void doStuff(MySuperClass goon) {
  MySuperClass localGoon;
  if (goon instanceof MyChildClass) {
    localGoon = new MyChildClass(goon, goon.getChildField());
  } else {
     localGoon = new MySuperClass(goon);
  }
  localGoon.modifyShit();
  localGoon.doStuff()
}

Well, aside from the fact that your goon.getChildField() is unlikely to work there (goon is MySuperClass not MyChildClass), if you have child specific cloning behaviour you should have a virtual clone method on the superclass which would allow:
code:
void doStuff(const MySuperClass &goon) {
  std::auto_ptr<MySuperClass> localGoon(goon.clone());
  localGoon->modifyShit();
  localGoon->doStuff();
}

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.
Those are all examples of pointer semantics anyhow and are not even addressing implicit calls of constructors

Mustach fucked around with this message at 16:32 on Sep 26, 2011

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

Zombywuf posted:

Well, aside from the fact that your goon.getChildField() is unlikely to work there (goon is MySuperClass not MyChildClass), if you have child specific cloning behaviour you should have a virtual clone method on the superclass which would allow:
You're addressing a totally different design concern, the example obviously illustrates the intended point.

baquerd
Jul 2, 2007

by FactsAreUseless

Orzo posted:

You're addressing a totally different design concern, the example obviously illustrates the intended point.

He's right though, sloppy code on my part and the Dog/Cat example illustrates this better.

Eggnogium
Jun 1, 2010

Never give an inch! Hnnnghhhhhh!

tef posted:

Where other languages eschew complexity C++ embraces it with open arms and its tongue wagging. Being 'hard to learn is a symptom, along with the other symptoms of being hard to implement, hard to debug, etc.

Here's a horror: Scrolling past your avatar in IE9 slows the browser down to a crawl.

Dicky B
Mar 23, 2004

Zombywuf posted:

References being invisible and impossible to manipulate separately to values is the real horror.
This is why Pascal is probably the best beginner's language. The distinction between references and values and why that disparateness is so important gets hammered home early on, but in a relatively safe environment.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Mustach posted:

Those are all examples of pointer semantics anyhow and are not even addressing implicit calls of constructors

He was asking why it would be useful to not have default constructors called when objects are declared. In C#, it's useful because there is no pointer-specific syntax.

Oh, and

code:
SomeThing thing;
if(tryToDoAThing(butts, out thing)){
   thing.IsUseableNow;
}

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!
code:
out
is a horror

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.

baquerd posted:

He's right though, sloppy code on my part and the Dog/Cat example illustrates this better.
It doesn't, because C and C++ are not Java or C#, variables are objects, not references to objects. The equivalent C++ code to that example is
code:
IAnimal *animal;
if (wantCat){
  animal = new Cat();
}else{
  animal = new Dog();
}
animal->MakeNoise();
and of course animal isn't initialized to the address of some invisible default-constructed IAnimal object before the if-else.

Monkeymon posted:

code:
SomeThing thing;
if(tryToDoAThing(butts, out thing)){
   thing.IsUseableNow;
}
That is a legitimate example (when SomeThing is a struct). The others are crap.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



Mustach posted:

That is a legitimate example (when SomeThing is a struct). The others are crap.

I don't see any problem with the other examples - maybe I've lost track of exactly what everyone is arguing about? Some of you guys seem to be talking past each other.

baquerd
Jul 2, 2007

by FactsAreUseless

quote:

It doesn't, because C and C++ are not Java or C#, variables are objects, not references to objects.

Right, pretty much all of the strongly typed non-C++ world expects an uninitialized object to be a reference to a null or undefined object (edit: or actually be a null/undefined object), not to have it initialized by default for us.

baquerd fucked around with this message at 17:38 on Sep 26, 2011

Zombywuf
Mar 29, 2008

baquerd posted:

Right, pretty much all of the non-C++ world expects an uninitialized object to be a reference to a null or undefined object, not to have it initialized by default for us.

The fact that you said uninitialised object rather than uninitialised variable demonstrates why the non C++ way is a horror.

nielsm
Jun 1, 2009



Munkeymon posted:

If you need access to an object in the finally block of a try, you have to declare it outside of the try, but you do not have to instantiate it outside the try.
Well, C++ doesn't have finally blocks, which can be annoying until you remember you're supposed to put your cleanup logic in your destructors. Then it isn't a problem all of a sudden. It's like garbage collection just better. ("C++ doesn't need garbage collection, because it doesn't produce garbage.")

Example, I have a handle value I need to close when a block is left, even if an exception is thrown:
code:
class AutoHandle {
  HANDLE h;
public:
  AutoHandle(HANDLE h) : h(h) { }
  ~AutoHandle() { CloseHandle(h); }
};

void leek() {
  AutoHandle h(CreateHandle());
  throw "oh poo poo"; // this line is a horror btw
  // no leak
}
A bit of extra code up front, but it gets you a reusable component so it's not actually a loss.


baquerd posted:

Or suppose you want a placeholder member variable at the object level that will be defined in constructor arguments:

code:
class foo {
  final Object butts;
  foo(Object butts) {
     this.butts = butts;
  }
Why would you want an instantiated butts at declaration? Hint: you wouldn't and it would actually break this.

What you do in C++:
code:
class foo {
public:
  const Object butts;
  foo(Object const & butts) : butts(butts) { }
};
Pass a reference to a const Object in (faster pass by value, but still allows you to use a temporary unlike using a pointer type or a non-const reference), then initialise the butts field by its copy constructor from the argument. This is also the same syntax used to call superclass constructors.

Zombywuf
Mar 29, 2008

nielsm posted:

Pass a reference to a const Object in (faster pass by value, but still allows you to use a temporary unlike using a pointer type or a non-const reference), then initialise the butts field by its copy constructor from the argument. This is also the same syntax used to call superclass constructors.

That's what I said, but by then the rest of the thread had forgotten we were talking about C++.

Standish
May 21, 2001

thelightguy posted:

I don't see any practical usage for an uninitialized variable.
Do you work on Debian by any chance?

baquerd
Jul 2, 2007

by FactsAreUseless

Zombywuf posted:

The fact that you said uninitialised object rather than uninitialised variable demonstrates why the non C++ way is a horror.

An object is conceptually different than a normal variable in that it can support member methods, variables, and objects. We're also talking about constructors here in particular...

What don't you like about it? That it means I'm not thinking in terms of specific memory allocation and pointers?

Zombywuf
Mar 29, 2008

baquerd posted:

An object is conceptually different than a normal variable in that it can support member methods, variables, and objects. We're also talking about constructors here in particular...

What don't you like about it? That it means I'm not thinking in terms of specific memory allocation and pointers?

object != variable

A variable is a name used to refer to a value, an object is a value.

baquerd
Jul 2, 2007

by FactsAreUseless

Zombywuf posted:

object != variable

A variable is a name used to refer to a value, an object is a value.

We're just operating under different terminology systems here. An object is a classifying description of a variable, a specific object's class is a variable type, a value is a value is a value.

Mustach
Mar 2, 2003

In this long line, there's been some real strange genes. You've got 'em all, with some extras thrown in.

baquerd posted:

What don't you like about it? That it means I'm not thinking in terms of specific memory allocation and pointers?
But, you were? You didn't like how SomeType blah; would allocate memory for blah and possibly call a function. That's what started this whole thing, man!

raminasi
Jan 25, 2005

a last drink with no ice
Which is the bigger horror: C++, or the discussions people end up having about it?

ephphatha
Dec 18, 2009




We can still rag on Java right?

Ran into an issue where I wanted to be able to copy any object that was marked as copyable. No problem I figured, I seem to recall java had a cloneable interface, let's look it up to find out how to use it.

Cloneable posted:

Note that this interface does not contain the clone method. Therefore, it is not possible to clone an object merely by virtue of the fact that it implements this interface.
:smith:

Internet Janitor
May 17, 2008

"That isn't the appropriate trash receptacle."
Cloneable is fundamentally a problem because Object.clone() Doesn't specify deep or shallow copy semantics.

edit: No, we are not having a "mutable state is a horror" rant.

Munkeymon
Aug 14, 2003

Motherfucker's got an
armor-piercing crowbar! Rigoddamndicu𝜆ous.



nielsm posted:

Well, C++ doesn't have finally blocks, which can be annoying until you remember you're supposed to put your cleanup logic in your destructors. Then it isn't a problem all of a sudden. It's like garbage collection just better. ("C++ doesn't need garbage collection, because it doesn't produce garbage.")

Yeah, I thought he was asking why it was a useful feature (to not call a default constructor) in C#. I know my C(++) is too rusty, so I haven't been talking about those languages.

finally blocks are pretty boss, tho :kiddo:

Orzo
Sep 3, 2004

IT! IT is confusing! Say your goddamn pronouns!

nielsm posted:

("C++ doesn't need garbage collection, because it doesn't produce garbage.")
This quote is ridiculous, C++ produces plenty of garbage that you need to clean up yourself.

TasteMyHouse
Dec 21, 2006
RAII + boost smart pointers take care of most of it. Garbage collection isn't a panacea either.

Adbot
ADBOT LOVES YOU

Brecht
Nov 7, 2009

baquerd posted:

We're just operating under different terminology systems here. An object is a classifying description of a variable, a specific object's class is a variable type, a value is a value is a value.
You appear to have a fundamental misunderstanding of type systems, and/or a crippling lack of specificity in your language. There is no "terminology system" in which "An object is a classifying description of a variable" is true as a general statement.

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply