Jump to content

  • Log In with Google      Sign In   
  • Create Account

m3mb3rsh1p

Member Since 27 Mar 2008
Offline Last Active Yesterday, 06:21 PM

Posts I've Made

In Topic: Introducing Stanza: A New Optionally-Typed General Purpose Programming Langua...

17 May 2016 - 07:37 PM

Congratulations on the achievement and thanks for sharing. I must say, however that "A first taste of Stanza" provided on the Home Page could be made more palatable.

 

Would you consider a simpler, real-world example? Your story about the origins of the language would be well served with an example such as a calculator or guessing game.

 

This would help to show what Stanza makes easier.


In Topic: Why is my struct destructor not called?

08 April 2016 - 09:24 AM

@Bitmaster...

 

I said pointers must be used because they are the language facility for managing object... "lifetime," for lack of a better word. Sorry you caught my post before I edited it to reflect my concerns about turning to "advanced concepts" not placement new specifically. The OP asked "Why am I not getting Destruct A [500]?!." The answer, in my opinion should have been something like "Because you need to call "delete a" on a A* or exit the scope which does not automatically happen when you assign." The assignment was addressed early but I reproach the jump to topics about optimization, stack, free-store, dynamic allocation, placement new all to avoid the most basic of C++ concepts: pointers and new+delete.

 

A user-defined type need not allocate any memory to have a non-trivial destructor but the "basic" way of taking control of an object's lifetime away from the automatic scoping is to use a pointer. Surely it is folly to be suggesting that pointers+new+delete = dynamic allocation = free store = slow = much typing = avoid, avoid, avoid?? The OP wanted to dynamically destroy (ie before end of scope)  why are we trying to concoct a static allocation??

 

The OP clearly hit a gotcha in expecting the destructor to be called within the scope of the function. Pointers are necessary, irrespective of the language facility, allocator, container or custom class used to implement RAII / reduce typing / avoid arrow dereferencing / avoid free-store...etc. C/C++ programmers MUST know that they are responsible for their object's lifetime from the moment they declare a variable. This is the C/C++ way.

 

Automatic initialization+destruction and support structures exist to allow the programmer to delegate that responsibility not be relieved of it. "Thou shalt assume responsibility for this object's lifetime, on my behalf, from point A (e.g initialization) to point B(e.g end of scope or reset()). Placement new, manual destructor call, and all the other expert "implementations" of handling object lifetime must not change "Good Practice" in using variables/pointers/objects/references especially in main() or any other user-level function.

 

My example was meant to demonstrate the awareness a programmer should have of object lifetime, with particular respect to end of scope which is why I showed the unique_ptr example as one way of delegating responsibility and avoiding manual new+delete. "...an emphatic no." to the use of free store is a bit extreme. If one prefers to dabble in stack-only allocation then they are free to place "new" there, even for unique_ptr.

 

It is certainly interesting to explore the advanced concepts related to object allocation but all that "expert" knowledge belongs in "encapsulation." "General Programming" should be a place to exemplify good coding practices, moreso than "For Beginners" IMO. Bjarne Stroustrup and most of the "top brass" regularly bemoan the tendency of experts to turn basic questions into in-depth analyses of advanced language concepts instead of demonstrating the virtues and wonders of simplicity.

 

"The Pointer" is basic C/C++. It is what clearly defines the languages from Java, C# and others. The years have afforded us facilities to delegate object lifetime management but it remains our greatest advantage that we can say and aspire to guarantee that a particular scope behaves as it appears (as long as we don't go fighting the language with "expert" tricks).


In Topic: Why is my struct destructor not called?

08 April 2016 - 06:37 AM

Hmm, the replies seemed to jump straight to advanced concepts, skipping the basic new + delete which is how C++ works at the basic level:

    A *a = new A;
    a->val = 500;

    delete a;
    a = new A();
    printf( "Finally %d\n", a->val );
    a->val = 300;

    delete a;
    return 0;

The recommended practice these days is to use the standard library, but the point to remember is that pointers MUST be used if object destruction is needed before exiting scope.
 

#include <memory>

struct A { int val; };

int main()
{
    std::unique_ptr a{ new A};
    a->val = 500;

    a.reset(new A);
    printf("Finally %d\n" a->val);
    a->val = 300;
}

I believe manual scoping might work as well in some case but here, it seems you need "a" for the entire scope...

int main()
{
    A a;
    a.val = 500;
 
    {
        A b;
        b.val = 300;
        a.val = b.val;
        printf("Destroying b...\n");
    }
}

In Topic: Need help understanding line in code snippet for linked list queue please.

29 March 2016 - 03:36 AM

Thanks for the amazing trivia, frob. I didn't know that the x86 microcode was so sophisticated. If there's one take-away from this, it should be that programmers are wiser to name such oft-used utilities. It makes for easier mental parsing and future maintenance. I'm pretty sure a SWAP macro would have been possible when that text book was written.

 

Other examples that I sometimes find unnecessarily complicated :

-"shift left when multiplying by two." if one doesn't trust the compiler to make this one optimization then just write a template mult() or even just mult2() function.

 

- recursion of incomplete concepts such as factorial. Even mathematicians use "if" and "where"


In Topic: casting double* to float*

19 March 2016 - 12:58 AM

@nfries88 I was exploring double to float conversion using casts to see how accuracy would be lost due to multiplication by factors of 10 (naive, I know). I have often read that double and float can represent sooo many decimal points and huuuuge whole numbers so I wasn't expecting to see my naive version of an error pop up after 5 loops or less.

 

It was a sobering realisation that even floating point limits can be easily exceeded by multiplying seemingly small quantities, especially since they are used in the oft-mentioned "critical loops", "engine cores," "numeric libraries." I started appreciating things like media compression artifacts, 3D graphics clipping, statistical / mechanical errors...

 

I also wanted to see whether the compiler performs numeric conversion in contrast to truncation of integer types. I'm not familiar with the binary representation  of ieee floating point but I had the sense that even simple truncation would not be as error-prone as short(int). I know some processors provide double to float instructions so I was also hoping / checking that a double would truncate to (whole).(fraction) and not just read the bits that happen to occupy the lower 32 bits. (whose meaning is unfamiliar to me)

 

Before frob mentioned the 6 digits of precision, the "errors" were surprising because of the presumption I held about the level of precision. The final cast was interesting to me because I assumed the "error" was due to float inaccuracy propagation vs double and that casting the more accurate double would yield a more accurate float.

 

I just had this naive impression that ieee float dealt with the int-overflowing-multiply-by-10 by incrementing an exponent such that it could handle much larger values; e.g. 10 to the 10 "felt" possible with little error. On the fraction part, I "knew" shifting the decimal point would favour double  but a clear "error" in the fraction part when doing float(double) was a shock.

 

From this mix of results, I'll be striving to keep numeric calculations within limits. I've noticed that scaling down e.g by 10 or 100 works against loss of accuracy ie it seems better to work using fractions when aiming for accuracy, by my naive observations.


PARTNERS