|
One question to start with - do you have a copy of the C++ Standard? That would probably explain the rationale for allocators better than anything else. It's $30 from ANSI[^] and can be very useful to have a copy of.
jens rasmussen wrote:
After having allocated a new node-object, why does one use value_allocator.construct() to construct the value instead of just passing it by assignment? I have checked out the SGI and GNU implementation of stl_tree.h, and they just use assignment for bool, size_type and pointer values,
bools, size_type and pointers can have no special semantics on assignment, as they're simple data. However, other objects can, as assignment should involve destruction as well as construction.
jens rasmussen wrote:
- After I have allocated new space for my struct, can I just do a struct_allocator.construct() on it, or am I supposed to only do a stack_allocator.construct() on the stack element contained?
the struct_allocator.construct() should call to stack_allocator.construct(), so should be OK, I guess.
|
|
|
|
|
Hi Stuart - and thanks for your reply!
Yeah - I probably have all the relevant books. The only part I think is missing from every explanation of Allocators, is how to use them as a library developer.
Personally, I think that the best explanation is given by Matthew H. Austern in:
http://www.ddj.com/cpp/184403759
Your answer regarding why one does not use assignment/placement new, was very adequate (and a little humiliating I might add ) - just what I needed to put it all into place!
Regarding your answer to my struct problem - I personally think that I must do a stack_allocator.construct() on the stack element and either just leave the simple data be, or if a value is provided, use assignment (It is exactly the same problem as when allocating nodes, only value_type is replaced by stack). I can't see how struct_allocator.construct() should be able to call stack_allocator.construct() - any comments?
Best regards!
Jens
|
|
|
|
|
jens rasmussen wrote: why one does not use assignment/placement new
It's probably OK to use placement new in the standard case - VC++'s default allocator::construct is implemented using placement new. However, the whole point of the allocator is to allow users to change the standard memory allocation strategy, so you should really use it whenever you a) allocate, b) construct, c) destruct or d) deallocate memory. So, when you'd naturally write 'Something* p = new Something();', you need to use allocator::allocate and allocator::construct instead.
jens rasmussen wrote: I can't see how struct_allocator.construct() should be able to call stack_allocator.construct() - any comments?
Ummmm - sorry, I didn't say what I meant to say, which was - if struct_allocator.construct() is implemented using the struct's default constructor (through placement new) then it will call stack's default constructor.
|
|
|
|
|
Wow, I real discussion about software development. It's been so long since I've seen one I just kept reading it over and over. Mesmerized by the illusion that my life as a developer has meaning beyond showing up and collecting my paycheck. I'm ok now though.
|
|
|
|
|
led mike wrote: real discussion about software development
I generally have several of those a day at work - I work for company developing safety-critical software, so the management does actually care that we do the job right
|
|
|
|
|
Stuart Dootson wrote: I work for company developing safety-critical software, so the management does actually care
I work for and with a bunch of monkeys
|
|
|
|
|
What kind of monkey business is that? Is that why you seem to go bananas after reading some of the posts on Code Project?
"We make a living by what we get, we make a life by what we give." --Winston Churchill
|
|
|
|
|
George L. Jackson wrote: Is that why you seem to go bananas after reading some of the posts on Code Project?
Hey! I resemble that remark.
|
|
|
|
|
Hi All,
I'm having trouble getting a file into a list. What I don't want to do is read a line (string), and then push_back() for each character.
Is anyone aware of the ctor I'm interested in which takes an ifstream ?
I can't believe how rusty I am with STL...
Thanks,
Jeff
std::list< char > certificate;
std::ifstream file;
<br>
file.open( "..//smime.p7b", std::ios::binary );
<br><br>
if( false == file.is_open() ) { return 1; }
<br><br>
char c;
while( file.get( c ) )
{
certificate.push_back( c );
}
<br><br>
std::cout << "Certificate Size: ";
std::cout << certificate.size() << std::endl;
<br><br>
file.close();
|
|
|
|
|
Why do you need this file loaded in a list<char> object instead of a vector<char> ? I mean, wouldn't something like this suffice (error checks omitted)?
vector<char> buffer;
ifstream file;
size_t fileSize;
file.open( "..\\smime.p7b", ios::binary );
file.seekg( 0, ios_base::end );
fileSize = file.tellg();
buffer.resize( fileSize );
file.seekg( 0, ios_base::beg );
file.read( &buffer.front(), buffer.size() );
|
|
|
|
|
Hi gleat,
gleat wrote: Why do you need this file loaded in a list<char> object instead of a vector<char>?
I'm using it to help me parse the input. With a list (or stack) once a top/pop occurs, I don't have to worry about adjusting a pointer (or index) into the array. Also, I can push back values without concern for book keeping.
Jeff
|
|
|
|
|
Using std::list like this is very inefficient; it's essentially a doubly liked list with -- in your case each -- each node containing a single char . You'd be better off using a std::vector .
Steve
|
|
|
|
|
Hi Steve,
Thanks for the reply.
Stephen Hewitt wrote: Using std::list like this is very inefficient;
I should have stated the files are small - less than 5KB. I desired to simplify insertion and extraction. With the list, both operations are O(1) (constant time), with a memory footprint ~= 3 times original files size. I do not need random access (vector). Also, I do not need to search.
Stephen Hewitt wrote: You'd be better off using a std::vector.
With vector, I loose O(1) extraction (extraction is linear from front or middle). Insertion is O(1) if at the end. But I have to manage an index or pointer. However, size ~= 1x.
Taking from SGI's site on vectors:
Vector is the simplest of the STL container classes, and in many cases the most efficient. As the docs state, "in most cases". In my case, I am working on a parser/scanner (no need for the tokenizer). I believe if I wanted to lessen memory needs, I could use an slist. But out of habit, I grabbed a list.
In the end, I am willing to trade memory for time (and simplicity).
Thanks for the input,
Jeff
|
|
|
|
|
Why are you inserting anything into the input file? It sounds like you're going to be mutating the input structure to form the output? When parsing, I prefer to use a pure functional approach, so that the input is immutable, and I form a separate output structure. Having said that, I know nothing about the format you're parsing
|
|
|
|
|
Eeep - I wouldn't use a list for that - as the others have said, use a vector.
Once you get past that, the easiest way to populate the vector is like this (or a list, actually, as shown):
<code>std::ifstream file (filename);
std::vector<char> vectorStore(std::istream_iterator<char>(file), std::istream_iterator<char>());
{or}
</code><code>std::list<char> listStore(std::istream_iterator<char>(file), std::istream_iterator<char>());</code> This may discard line-endings in text (as opposed to binary) mode - I'm not sure.
An alternative (and more efficient for big files) approach would be to reserve enough space in the vector before reading the file:
std::vector<char> fileContents;
struct _stat stat;
if (_stat(filename, &stat) == -1) throw std::runtime_error("Can\'t open " + file);
fileContents.resize(stat.st_size);
std::ifstream file(filename);
std::copy(std::istream_iterator<char>(file), std::istream_iterator<char>(),
fileContents.begin()); Once you have the contents in a vector, parse them from there. Use iterators to keep track of input location.
|
|
|
|
|
Hi Stuart,
I went into detail on my choosing of a list over vector with Steve above (and concluded I could use a slist to lessen memory requirements). But I believe I could use your code on the stream. Thanks.
Jeff
|
|
|
|
|
One other thing - one detail I didn't notice was that your file is a binary format - strictly, you should be using unsigned char s, I guess, so that signs don't get in the way. Probably doesn't make any pragmatic difference, though.
|
|
|
|
|
Hi Stuart,
Stuart Dootson wrote: strictly, you should be using unsigned chars,
Got it... I was being lazy before I did the #define byte unsigned char
Thanks,
Jeff
|
|
|
|
|
Jeffrey Walton wrote: file.open( "..//smime.p7b", std::ios::binary );
A P7B file is a Cryptographic Message Sytnax Standard (PKCS #7). As such, it is specified in ASN.1 notation.
ASN.1 is an interesting beast. To parse, it requires more of a 'Message Cracker' (similar to Windows Messaging), rather than a full fledged parser/tokenizer (HTML, XML, etc).
Jeff
|
|
|
|
|
Dear all,
Could you help me giving a sample of a function which return bitset (Standar Template Library). Please reply as soon as possible. I am waiting...
Thanks.
Regards,
Ian
|
|
|
|
|
#include <bitset>
std::bitset<12> BitsetWithNthBitSet(int n)
{
return std::bitset<12>().set(n, true);
}
|
|
|
|
|
Stuart Dootson wrote: std::bitset<12> BitsetWithNthBitSet(int n) { ...
In the example above you mention the N of bitset<n> is 12. How about if you don't know the 'N'?
-- modified at 22:54 Thursday 8th November, 2007
|
|
|
|
|
|
You can only use std::bitset if N is fixed at compile-time. If you don't know N until runtime, you can use std::vector<bool> or (as Rob said) boost::dynamic_bitset .
|
|
|
|
|
Ontanggabe Parulian wrote: In the example above you mention the N of bitset is 12. How about if you don't know the 'N'?
i feel, you need to N , otherwise how you determine which bit you have to set.
"Opinions are neither right nor wrong. I cannot change your opinion. I can, however, change what influences your opinion." - David Crow Never mind - my own stupidity is the source of every "problem" - Mixture
cheers,
Alok Gupta
VC Forum Q&A :- I/ IV
Support CRY- Child Relief and You
|
|
|
|