I'd have to say I'm no expert on using the STL. Here's my problem, I have a class Called LdapClientManager which maintains a number of LDAP clients that are managed by ID. The container holding the LdapClients is declared as a member variable i.e.
typedef std::map<int, LdapClient *> LdapClientMap;
LdapClientMap _ldapClientMap;
The following function fails to compile with the error:
LdapClient * LdapClientManager::getLdapClient(unsigned int templateID)
{
// Do we have an LdapClient
LdapClientMap::const_iterator it = _ldapClientMap.find(templateID);
if (it == std::map::end) {
// no existing client, lets create it
LdapClient * ldapClient = new LdapClient();
if (ldapClient == NULL) {
// TODO: handle out of memory condition
}
_ldapClientMap[templateID] = ldapClient;
return ldapClient;
}
return it->second;
}
Unfortunately I get the following error at compile time, what does it mean. I haven't found a solution in google as yet.
LdapClientManager.cc: In member function LdapClient*
LdapClientManager::getLdapClient(unsigned int)':
LdapClientManager.cc:33:template class std::map' used without template parameters
Replace std::map::end with _ldapClientMap.end().
Also, new never returns 0, it throws an exception if the allocation fails.
Note that the program can be made much shorter.
LdapClient * LdapClientManager::getLdapClient(unsigned int templateID)
{
LdapClient *& value = _ldapClientMap[templateID];
if (value == 0)
value = new LdapClient();
return value;
}
It means exactly what it says it means. std::map is a class template. It is not a class in and of itself. It needs template parameters, like you used when you defined the LdapClientMap type. Later, you say std::map::end, and the compiler says that needs parameters, too.
But you probably meant _ldapClientMap.end(). Each map has its own end; end is not a static function, so you need to call it on an instance. If it were static, you would have needed to provide template parameters, just like when you defined the type: std::map<int, LdapClient*>::end.
std::map::end() is a member function of the container instance and not a universal value, so you'll need to check the result of std::map::find() against _ldapClientMap.end().
Another couple of suggestions to improve the code:
Standard C++ containers have value semantics (they want to store the actual object and not a pointer to the object). If you really need to store pointers to LdapClients instead of the LdapClient objects themselves, I would strongly recommend wrapping them in an appropriate smart pointer like boost::shared_ptr (not std::auto_ptr, which will not work). This way, the automatic memory management of the std::map will still work and destroy the objects as intended. If you don't want to use a smart pointer or put the actual LdapClient object into the container, you will have to manually manage the objects' lifetime and call delete when appropriate to prevent memory leaks. My preference would be to change the type of the map to std::map unless the LdapClient objects are polymorphic.
Unless you are using a very out of date compiler, checking the result of regular new() against 0 or NULL will not yield any new insights as new throws a std::bad_alloc these days when it can't allocated memory for whatever reason.
Instead of using _ldapClientMap[x] = y; to insert a new element, I would use _ldapClientMap.insert(LdapClientMap::value_type(x,y)) as the latter will not overwrite an existing value for key x (which the former will do) and will return 'false' in case the key already exists in the map. That is of course if that is your intention.
LdapClientMap _ldapClientMap;
You should avoid using names with a leading underscore. Technically it is undefined behavior, even if the compiler allows it because by using it you conflict with current or future reserved names.
Related
I am working on a project for my University where i have to implement a Hash table. I am quite new to c++, so please forgive me if I am not specific enough or if I have completely wrong assumptions.
Soo..my main problem is that I have a so called "Bucket" which is a struct in my program and which contains a pointer array of N(template parameter) places.
struct Bucket {
T *kptr{ nullptr };
Bucket *bptr{ nullptr }; //For overflow chains (linear Hashing)
Bucket(Bucket *bptr = nullptr) : kptr(new value_type[N]),bptr(bptr) {}
~Bucket() { if(bptr) delete[] bptr; if (kptr) delete[] kptr; }
};
In my main Class named My_Set for example I have an additional Bucket *table of [1<
My first assumption was to initialize the kptr array to nullptr and then in the insert method to make something like
void insert(Bucket &bkt, T &key) {
for (int i=0; i<N, ++i) {
if (bkt.kptr[i]) { //Check on nullptr!
kptr[i] = key;
}
}
}
But that´s not possible because then kptr should be Bucket T **kptr and not Bucket *kptr as far as i understood it.
So, is there any other efficient way to check one single field of an array if it has been assigned to an Object already or not?
IMPORTANT: I am not allowed to use STL Containers, Smart Poitners and similar things which would make the whole thing much easier.
Thanks!
Check whether pointer in pointer array is already “filled”
... So, is there any other efficient way to check one single field of an array if it has been assigned to an Object already or not?
Yes: Initialize the pointer to nullptr. Then, if the pointer has a value other than nullptr, you know that it has been pointed to an object.
However, your professor is correct that your checking is inefficient. On every insert you iterate through all previously inserted objects.
That is unnecessary. You can avoid trying to check whether any of the pointers have been assigned by remembering where the next free pointer is. How can we "remember" things in algorithms? Answer: Using variables. Since you must remember for each instance of your container, you need a member variable.
Since you are using this new variable to remember the next free pointer, how about we name it next_free. Now, considering that the variable must refer to an existing object, what type should it have? A reference would be a good guess, but you must also be able to reassign it once an element is inserted. What can refer to an object like a reference, but can be reassigned? Answer: A pointer. Since this pointer is going to point to a pointer to T, what should be its type? Answer: T**. What should it be initialized to? Answer: The address of the first element of kptr. With such member, insert can be implemented like this:
void insert(T &key) { // why would there be a Bucket argument for insert?
*next_free++ = new T(key); // Note: Do not do this in actual programs. Use
// RAII containers from the standard library instead
}
then kptr should be Bucket T **kptr and not Bucket *kptr as far as i understood it.
Correct. A T* can not point to an array that contains pointers (unless T happens to be a pointer) - it can point to an array of T objects. A T** can point to an array of pointers to T.
Instead of pointers to separately allocated objects, it would be more efficient to use a flat resizable array. But since you are not allowed to use std::vector, you would then have another standard container to re-implement. So consider whether the efficiency is worth the extra work.
I'm designing a class for my application that implements a lot of standard shared pointers and usage of standard containers such as std::map and std::vector
It's very specific question to the problem so I just copied a piece of code
from my header for clarification purposes..
here is a snapshot of that declarations from the header:
struct Drag;
std::map<short, std::shared_ptr<Drag>> m_drag;
typedef sigc::signal<void, Drag&> signal_bet;
inline signal_bet signal_right_top();
and here is one of the functions that uses the above declarations and a temporary shared_ptr which is intended to be used not only in this function but until some late time. that means after the function returns a shared pointer should be still alive because it will be assigned at some point to another shared_ptr.
void Table::Field::on_signal_left_top(Drag& drag)
{
m_drag.insert(std::make_pair(drag.id, std::make_shared<Drag>(this))); // THIS!
auto iter = m_drag.find(drag.id);
*iter->second = drag;
iter->second->cx = 0 - iter->second->tx;
iter->second->cy = 0 - iter->second->ty;
invalidate_window();
}
the above function first insert a new shared_ptr and then assigns the values from one object into another,
What I need from your answer is to tell whether is it safe to insert temporary shared_ptr into the map and be sure that it will not be a dangling or what ever bad thing.
According to THIS website the above function is not considered safe because it would much better to write it like so:
void Table::Field::on_signal_left_top(Drag& drag)
{
std::shared_ptr pointer = std::make_shared<Drag>(this);
m_drag.insert(std::make_pair(drag.id, pointer));
auto iter = m_drag.find(drag.id);
*iter->second = drag;
// etc...
}
well one line more in the function.
is it really required to type it like that and why ?
There's no difference between the two functions in regard to the std::shared_ptr, because the std::make_pair function will create a copy of the temporary object before the temporary object is destructed. That copy will in turn be copied into the std::map, and will then itself be destructed, leaving you with a copy-of-a-copy in the map. But because the two other objects have been destructed, the reference count of the object in the map will still be one.
As for handling the return value from insert, it's very simple:
auto result = m_drag.insert(...);
if (!result.second)
{
std::cerr << "Could not insert value\n";
return;
}
auto iter = result.first;
...
The code in the example given is different from your example code, because it is using the new operator instead of std::make_shared. The key part of their advice is here:
Since function arguments are evaluated in unspecified order, it is possible for new int(2) to be evaluated first, g() second, and we may never get to the shared_ptr constructor if g throws an exception.
std::make_shared eliminates this problem - any dynamic memory allocated while constructing an object within std::make_shared will be de-allocated if anything throws. You won't need to worry about temporary std::shared_ptrs in this case.
I have a class :
class A
{
private:
vector<int> x;
public:
const vector<int>& immutable_data() {
return x;
}
vector<int>* mutable_data() {
return &x;
}
}
Now if i use this class , in my code , do i have to check if the pointer returned by the mutable_data() is null or not (given that i know the structure of this class). Personally i think i don't have to because i know there exist a secondary api which returns a const reference and so my pointer can never be null (I can't imagine of a scenario where this function would return me null ,even if it somehow does returns null, what would be the behavior of the const ref version in that case). Or should i say that i know its an address of an existing object on stack , so it cannot be null ? Is this the correct way to think or reason about this ? If any one thinks the other way , please give some example code.
For a more common case scenario in production code : if i use protocol buffers , i already know the generated code for my message templates (for eg: repeatedfields which are like stl containers), but do i still need to do null check every time i want to use the mutable api because they always return either by pointer or const reference.
returning by reference is not what i am looking for.
do i have to check if the pointer returned by the mutable_data() is null or not (given that i know the structure of this class)
In general, design elements like "have to check the pointer" depends on one of two things:
Does your design need to be provably safe?
If not, then does the design of A::mutable_data() dictate that it won't return null?
If (1), then you should invest in the kind of SAT-solver based tools which can test statically that your code won't access invalid memory.
If (2), I recommend that you consider the concept of Design by Contract -- it is a powerful one. If A::mutable_data()'s interface is specified not to return null, then it returning null would be a design defect in A::mutable_data().
Returning a null pointer usually means "I don't have any data for you". If the class will always have data, then, by design, the function will never return a null pointer. If that's the case, then code that uses the function does not need to check for null pointers. That's one of the guarantees that the function makes: "I won't ever return a null pointer".
I have a class which acts as a cache. It has the following private member:
std::map<std::string, Foo> _cache;
I need to write a getter for this cache which returns a reference, pointer, iterator or smart pointer to a Foo object stored in the cache. I want the client to be able to update the Foo object if required via the getter.
However, I don't want the getter to throw if the item is not found in the cache. Instead the client should test the returned value to determine if the item was found. However, I can be convinced to throw if you recommend this approach.
What return type would you recommend for my getter?
I'm using boost and C++98.
Sounds like you need a boost::optional<Foo&> return value (optional references). Your code should look like this:
class YourCache {
std::map<std::string, Foo> _cache;
public:
boost::optional<Foo&> FooByName(const std::string& name)
{
std::map<std::string, Foo>::iterator itr = _cache.find(name);
if(_cache.end() == itr)
return boost::none;
return boost::optional<Foo&>(itr->second);
}
};
getter doesn't throw :)
respects the already existing implementation of _cache (you don't have to change it to store smart pointers - or pointers in general)
gives no direct access to memory in client code (like returning Foo* would)
expresses the intent in the best way ("the return value is optional/could be missing")
offers an explicit and natural interface in client code:
For example:
// client code:
if (boost::optional<Foo&> result = YourCache.FooByName("FOO")) {
// only run if result is in cache
result->bar();
}
In your case references are out of question due to possibility of returning a null pointer. An iterator is a no go either, as you can't test, if it actually points to an element without access to .end() function of the cache, which is a private member. Unless you provide an interface to test is, but that's an overkill.
The only other option is to return a pointer. However that way you'd have to guarantee that the pointer remains valid throughout the whole time a caller uses it. One way to do it is to implement a map of shared pointers, that is:
std::map<std::string, boost::shared_ptr<Foo> > _cache;
That way, even if the object is thrown out of the cache, the caller would still be left with a valid pointer. And shared_ptr can be bool tested, so in case an item is not found in the cache, you could return an empty shared_ptr.
But too little is known about the context of the cache to tell you more (eg if synchronisation is needed, etc).
Use a boost::optional holding a Foo reference as your return value for your getter.
In order to make the discussion clear, I'm going to describe the problem in a very general manner, i.e. I will neither provide names of real classes nor will I describe the domain/context (however, I might if it turns out to be urgent).
Imagine class A. Let this class have 2 immutable fields, for instance x and y (please, notice, that these could be potentially big objects, i.e. inefficient to copy). Additionally, let these x and y be primary fields, i.e. only they are used in the implementation of ==/!= operators as well as hash-computing function.
Since A is immutable in terms of x and y, the idea is to let multiple instances of A (say a1 and a2) which have a1.x == a2.x a1.y == a2.y (i.e. a1 == a2) to implicitly have shared access to those x and y, so that there is no unnecessary duplication.
Moreover, now imagine that there is another field in A: z, which is secondary and mutable, and serves as a sort of behavior tweak for A. By design, it is desired to make this field shared among equal instances of A too. So, if I invoke a1.setZ(...) this change will also affect a2 because their access to z is shared.
As a result, we end up with a class A which has pure value semantics, but shares its members implicitly across equal instances. AFAIK such pattern is called Flyweight or aliasing.
One more detail before we move to the question. Most classes in the project are implemented using Pimpl idiom:
private:
class Private;
Private* p;
and class A is not an exclusion. That's why the proposed idea of implementing the scheme described above is as follows.
Use shared pointer to A::Private instead of raw one in
Pimpl idiom;
Have global set of shared pointers to A::Private;
In constructor of A to check whether a shared
pointer to suitable A::Private already exists in the set
(utilizing x and y of course), and if yes, then simply set p
to it, otherwise create new instance of A::Private and store
shared pointer to it in this set, and similarly set p to it;
A::Private's destructor should remove shared pointer to this from the set.
This looks like the most straightforward and intuitive implementation. However, the problem is that since this global set holds a shared pointer to A::Private, it means that even when all instances of corresponding A are destroyed, the reference counter will stay on 1, i.e. it will never reach 0, and thus the memory is never freed.
I thought it would be good if some shared pointers would offer a method to set lower bound for the reference counter. In this case, for example, I would simply set it to 1 which would mean that when it reaches 1 it frees the memory. Unfortunately, I haven't found any implementation of such behavior in popular libraries (Boost, Qt, Poco, etc.). Of course, I could do manual reference counting for my problem, but that just doesn't feel right and smells like reinventing the wheel.
Probably, there are other ways to solve this problem. Looking forward for your suggestions.
NOTE: I would like to immediately intercept any advising to transform the problem to pointer semantics which I am well aware of. I need the solution exactly for the scheme described above.
If I understood correctly what your design issue is, then I would let the global set contain weak, non-owning pointers (e.g. weak_ptr<>) which are able to check if they are dangling, yet they do not increase the reference count.
std::vector<std::weak_ptr<Private>> _objects;
Therefore, when all owning shared pointers to an object are destroyed, the object will be destroyed as well**.
Now your global set will be left with a dangling weak_ptr<>, but the nice thing is that you can check whether that pointer points to an object which is alive or not (use the lock() member function to obtain a possibly null shared_ptr<>. And if it doesn't, you won't dereference it:
// A simple, hypothetical loop through the collection of objects
// which does something, but checks whether the pointers are
// dangling before doing that something on a possibly dead object
// that would be Undefined Behavior)
std::for_each(_objects.begin(), _objecs.end(), [] (std::weak_ptr<Private> p)
{
std::shared_ptr<Private> sp = p.lock();
if (sp != nullptr)
{
sp->callMember(); // For instance...
}
});
If you also want to remove the corresponding weak_ptr<> to an object from the collection once the object gets destroyed, then you could use a custom deleter routine. Your routine will be invoked when the object is destroyed and will be passed the pointer to that object: at this point, before deallocating, you can erase the corresponding element from the set.
For example, a function that instantiates new objects of type A and returns a shared_ptr to it could look this way:
static std::shared_ptr<object> make_A()
{
std::shared_ptr<Private> sp(
new Private(), // Instantiate the object
[] (Private* p) // Set up the custom deleter...
{
// Remove the corresponding element from the vector...
_objects.erase(
// ...so let's find that element!
std::find_if(
_objects.begin(),
_objects.end(),
[p] (std::weak_ptr<priv> wp)
{
// lock() will return a null pointer if wp is dangling
std::shared_ptr<priv> sp = wp.lock();
// In case wp is not dangling, return true if and only
// if it points to the object we're about to delete
return ((sp != nullptr) && (sp.get() == p));
})
);
});
}
Here I assumed C++11, you could easily do the same in C++03 by replacing std::shared_ptr<> with boost::shared_ptr<>, std::weak_ptr<> with boost::weak_ptr<>, and lambdas with properly-defined functors.
Hope this helps.
Have you checked Boost.Flyweight out?