LinuxQuestions.org
Welcome to the most active Linux Forum on the web.
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 01-23-2011, 11:49 AM   #16
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Original Poster
Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454

Quote:
Originally Posted by johnsfine View Post
...
You should try to understand the "placement new" feature of C++ (ta0kira included an example of the syntax in his last post). That feature is the technically correct way to do both of your Point2D_cast methods that are now technically incorrect.

This "placement new" is a bit confusing because it doesn't allocate any new space. In this default form of placement new, it is really just a call to the constructor on existing space (previously allocated some other way).

C++ does not allow you to directly call a constructor. So in those cases where what you want is a direct call to a constructor, you use placement new.

Placement new can also be used when you want more interesting overrides of the allocation portion of an ordinary new.
I am trying to verify the statement in bold in C++ standard: http://openassist.googlecode.com/fil...2%25202003.pdf .

On page 80, in "5.3.4 New", I read:

Code:
1 The new-expression attempts to create an object of the type-id (8.1) or new-type-id to which it is applied.
  The type of that object is the allocated type. This type shall be a complete object type, but not an abstract
  class type or array thereof (1.8, 3.9, 10.4). [Note: because references are not objects, references cannot be
  created by new-expressions. ] [Note: the type-id may be a cv-qualified type, in which case the object cre-
  ated by the new-expression has a cv-qualified type. ]
        new-expression:
                    ::opt new new-placementopt new-type-id new-initializeropt
                    ::opt new new-placementopt ( type-id ) new-initializeropt
        new-placement:
                    ( expression-list )
        new-type-id:
                    type-specifier-seq new-declaratoropt
        new-declarator:
                    ptr-operator new-declaratoropt
                    direct-new-declarator
        direct-new-declarator:
                    [ expression ]
                    direct-new-declarator [ constant-expression ]
        new-initializer:
                    ( expression-listopt )
  Entities created by a new-expression have dynamic storage duration (3.7.3). [Note: the lifetime of such an
  entity is not necessarily restricted to the scope in which it is created. ] If the entity is a non-array object, the
  new-expression returns a pointer to the object created. If it is an array, the new-expression returns a pointer
  to the initial element of the array.
.

So, from the above I understand that allocation does occur - because of "dynamic storage duration".

I also learned about POD (Plain Old Data). On page 48:

Code:
  3.8 Object Lifetime                                                                                [basic.life]
1 The lifetime of an object is a runtime property of the object. The lifetime of an object of type T begins
  when:
  — storage with the proper alignment and size for type T is obtained, and
  — if T is a class type with a non-trivial constructor (12.1), the constructor call has completed.
  The lifetime of an object of type T ends when:
  — if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or
  — the storage which the object occupies is reused or released.
2 [Note: the lifetime of an array object or of an object of POD type (3.9) starts as soon as storage with proper
  size and alignment is obtained, and its lifetime ends when the storage which the array or object occupies is
  reused or released. 12.6.2 describes the lifetime of base and member subobjects. ]
.

And on page 52:


Code:
  3.9 Types                                                                                              [basic.types]
1 [Note: 3.9 and the subclauses thereof impose requirements on implementations regarding the representation
  of types. There are two kinds of types: fundamental types and compound types. Types describe objects
  (1.8), references (8.3.2), or functions (8.3.5). ]
2 For any object (other than a base-class subobject) of POD type T, whether or not the object holds a valid
  value of type T, the underlying bytes (1.7) making up the object can be copied into an array of char or
  unsigned char.36) If the content of the array of char or unsigned char is copied back into the
  object, the object shall subsequently hold its original value. [Example:
        #define N sizeof(T)
        char buf[N];
        T obj;                                       // obj initialized to its original value
        memcpy(buf, &obj, N);                        // between these two calls to memcpy,
                                                     // obj might be modified
        memcpy(&obj, buf, N);                        // at this point, each subobject of obj of scalar type
                                                     // holds its original value
   —end example]
3 For any POD type T, if two pointers to T point to distinct T objects obj1 and obj2, where neither obj1
  nor obj2 is a base-class subobject, if the value of obj1 is copied into obj2, using the memcpy library
  function, obj2 shall subsequently hold the same value as obj1. [Example:
        T* t1p;
        T* t2p;
                                                     // provided that t2p points to an initialized object ...
        memcpy(t1p, t2p, sizeof(T));                 // at this point, every subobject of POD type in *t1p contains
                                                     // the same value as the corresponding subobject in *t2p
   —end example]
.

So, from the last example it looks like my idea to use 'memcpy' is not that illegal within the limitations mentioned by myself and by ta0kira.

I carefully read ta0kira's suggestion and, of course, I understand the syntax, but where in the standard can I find the confirmation that no allocation occurs ?

Or at all I am using an outdated standard (year 2003) ?
 
Old 01-23-2011, 02:28 PM   #17
johnsfine
LQ Guru
 
Registered: Dec 2007
Distribution: Centos
Posts: 5,286

Rep: Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190Reputation: 1190
Quote:
Originally Posted by Sergei Steshenko View Post
So, from the above I understand that allocation does occur - because of "dynamic storage duration".
dynamic storage duration does not imply the new operation allocated the space. It implies the compiler is not responsible for the call to the destructor at the point the object goes out of scope.

Quote:
I also learned about POD (Plain Old Data).
You are correct that those actions (discussed above) that would otherwise be misuse of the assignment operator or memcpy are correct if the struct is POD. But I was under the impression that the constructor you defined technically made the struct non POD (I might be misremembering the details of "POD").

I understand the struct is conceptually POD, so using an assignment operator to overwrite unconstructed space will actually work, as will using memcpy to overwrite unconstructed space. I'm still bother by using a constructor for a class side by side with code that depends on the class being POD.

Regardless of the above, somewhat philosophical, issue: Why not learn how to use placement new to do the same job not only more cleanly, but also more efficiently. There is no need to construct the object then copy the result to where you want it. You can construct it directly where you want it.
 
Old 01-23-2011, 02:52 PM   #18
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
If the struct is actually going to be POD, I don't see why this can't be done entirely in C with a series of macros. Unless the example is just for instructional purposes, in which case the discussion should be a bit more general. Regarding assignments and copy-construction, C will do both byte-for-byte like memcpy.
Code:
#include <stdio.h>

struct mydata { char data[16]; };

int main()
{
        struct mydata a = { "hello" };
        struct mydata b = a, c;
        c = b;

        fprintf(stderr, "[%s] [%s] [%s]\n", a.data, b.data, c.data);
}
Kevin Barry

Last edited by ta0kira; 01-23-2011 at 02:56 PM. Reason: fixed grammar
 
Old 01-24-2011, 04:53 AM   #19
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Original Poster
Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by johnsfine View Post
dynamic storage duration does not imply the new operation allocated the space. It implies the compiler is not responsible for the call to the destructor at the point the object goes out of scope.



You are correct that those actions (discussed above) that would otherwise be misuse of the assignment operator or memcpy are correct if the struct is POD. But I was under the impression that the constructor you defined technically made the struct non POD (I might be misremembering the details of "POD").

I understand the struct is conceptually POD, so using an assignment operator to overwrite unconstructed space will actually work, as will using memcpy to overwrite unconstructed space. I'm still bother by using a constructor for a class side by side with code that depends on the class being POD.

Regardless of the above, somewhat philosophical, issue: Why not learn how to use placement new to do the same job not only more cleanly, but also more efficiently. There is no need to construct the object then copy the result to where you want it. You can construct it directly where you want it.
I don't mind learning placement-new; we've been discussing formal correctness of what I'm doing, so I wanted to make sure that suggested by others solutions are formally correct. Intuitively, and from my general understanding of how things work, placement-new appears to be correct, but I would like to be able to come up with a formal proof of correctness based on the C++ standard.

I.e. if/when I'm asked "why did you use placement-new", I'd like to be able not only to say "because johnsfine/ta0kira told me so", but to be able to say "johnsfine/ta0kira suggested the solution and according to clauses <such_and_such> of C++ standard the solution is indeed correct".

I will reread the relevant portions again and hopefully will be able to reach the correctness conclusion.
...
About objects in C++ (pages 4 .. 5 in the same standard) :

Code:
  1.8 The C++ object model                                                                       [intro.object]
1 The constructs in a C++ program create, destroy, refer to, access, and manipulate objects. An object is a
  region of storage. [Note: A function is not an object, regardless of whether or not it occupies storage in the
  way that objects do. ] An object is created by a definition (3.1), by a new-expression (5.3.4) or by the
  implementation (12.2) when needed. The properties of an object are determined when the object is created.
  An object can have a name (clause 3). An object has a storage duration (3.7) which influences its lifetime
  (3.8). An object has a type (3.9). The term object type refers to the type with which the object is created.
  4
 ISO/IEC                                                                           ISO/IEC 14882:2003(E)
1 General                                                                            1.8 The C++ object model
Some objects are polymorphic (10.3); the implementation generates information associated with each such
object that makes it possible to determine that object’s type during program execution. For other objects,
the interpretation of the values found therein is determined by the type of the expressions (clause 5) used to
access them.

Last edited by Sergei Steshenko; 01-24-2011 at 04:54 AM.
 
Old 01-24-2011, 02:41 PM   #20
ta0kira
Senior Member
 
Registered: Sep 2004
Distribution: FreeBSD 9.1, Kubuntu 12.10
Posts: 3,078

Rep: Reputation: Disabled
Alternatively, repost your question to comp.lang.c++.moderated. Several people will be more than happy to interpret the relevant portions of the standard. In fact, you probably don't even have to mention the standard and it will be addressed.
Kevin Barry

PS Is the rest of your code in compliance with the standard? I recall several places where you had undefined behavior. Placement-new vs. undefined should be an obvious choice.

Last edited by ta0kira; 01-24-2011 at 02:42 PM.
 
Old 01-24-2011, 03:14 PM   #21
Sergei Steshenko
Senior Member
 
Registered: May 2005
Posts: 4,481

Original Poster
Rep: Reputation: 454Reputation: 454Reputation: 454Reputation: 454Reputation: 454
Quote:
Originally Posted by ta0kira View Post
Alternatively, repost your question to comp.lang.c++.moderated. Several people will be more than happy to interpret the relevant portions of the standard. In fact, you probably don't even have to mention the standard and it will be addressed.
Kevin Barry

PS Is the rest of your code in compliance with the standard? I recall several places where you had undefined behavior. Placement-new vs. undefined should be an obvious choice.
I think only this:

Code:
    18  INLINE_C void Point2D_cast_to_this(ObjType obj)
    19    {
    20    Point2D t(0.0, 0.0); // any constructor call is good here - just to ensure basic initialization
    21                         // in order to be able to call methods later.
    22                         // care should be taken to make sure automatically called destructor of 't'
    23                         // doesn't cause problems.
    24    *obj = t;
    25    }
has undefined behavior - I am talking about the latest version - published in http://www.linuxquestions.org/questi...1/#post4234089 .
 
  


Reply


Thread Tools Search this Thread
Search this Thread:

Advanced Search

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
[SOLVED] Calling Nautilus "file manager" fails but Rhythmbox comes up instead Mark_in_Hollywood Ubuntu 6 12-09-2009 09:09 AM
Facing error while running "g++ 3.4.4" code in "g++ 4.3.3" Suranjit Ubuntu 2 10-08-2009 11:22 PM
usb serial driver failing when calling "usb_submit_urb" - why? DEF. Programming 3 05-28-2009 10:25 AM
ns:"error when calling class OldSim"&tclsh:"invalid command+child process exits abn." shojaru Linux - Newbie 0 03-05-2009 04:23 AM
odd recursion: calling "by hand" vs calling by cronscript... prx Programming 4 02-12-2005 04:59 PM

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

All times are GMT -5. The time now is 07:21 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
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration