Yes. However, making a const pointer seems rather pointless, as you will be able to allocate and deallocate memory for it, but you will be unable to change the contents.
You use delete object in C++ to delete an object. You can also implicitly delete the object, if it is automatic type, by going out of local scope.
#include<iostream> struct object { int m_data; }; void main() { object obj=new object; obj.m_data = 42; delete( obj ); return( 0 ); }
The const keyword transforms a variable into a constant. This means the constant cannot be altered via that constant's identifier. The const keyword can also be applied to a class instance method, such that the method will not alter a class instance's immutable members. Note that the const keyword is merely a programming aid that provides assurances a constant will not be altered inadvertently. However, it is still possible to alter the constant by using a non-constant pointer to the constant. However you have to make a conscious effort to override constant behaviour.
If you are referring to the character object 'char,' then here are a couple of uses:To create an object, use this:char object = 'a';To create an array of chars, use this:char array[10];To dynamically allocate an array of chars, use this:char array = new char[10];(Don't forget to delete the object with 'delete [] array')
You use delete to release the memory occupied by an object that is being pointed to by the pointer you delete. Provided all base classes have a virtual destructor, it doesn't matter what the type of pointer you actually delete is, so long as it is a type of class from which the object is actually derived. The destructor from the most-inherited class (the object itself) will be called first, which calls the destructors of its immediate base classes, and theirs, and so on until the object is completely released from memory.Note that you must not delete pointers to object references -- they must be nullified (not deleted) when they are no longer required. The referenced object will be deleted automatically when it falls from scope.
Yes, objects can be passed to functions in C++. The function's parameter determines how the object is handled by the function. The following examples show all the possible parameter variations:By reference:void foo(const MyObject& o);void foo(MyObject& o);By value:void foo(const MyObject o);void foo(MyObject o);By pointer:void foo(MyObject* p);void foo(const MyObject* p);void foo(MyObject* const p);void foo(const MyObject* const p);The pointer variations can be extended to include pointer to pointer variants and so on. However, it is not possible for any one function in the same namespace to be overloaded with all eight of these variations unless the return values are altered or dummy parameters are employed to eliminate the ambiguities. Under normal circumstances there will only be two overloads provided, one of which must accept a pointer. If additional overloads are provided, they must be pointer to pointer variants.Which variations are actually provided depend upon how the function interacts with the object. If the parameter is declared const then the function can only call the object's const member functions and access its mutable member variables. In the case of the pointer variations, this means those that declare const MyObject* parameters. Those with const p parameters only mean the pointer will always point at the same object within the function body.Passing objects by reference is the preferred method of passing objects to functions whenever an object is guaranteed to be known to exist. Passing by pointer is often provided as an overload to cater for those cases where an object may not exist; in some cases this may in fact be the only function provided. Regardless, passing by reference or by pointer is effectively the same as passing the object itself. Thus if the parameter is declared non-const, any changes made to the function's parameter will be reflected in the original object.Passing objects by value is rarely used and should be avoided as much as is possible. When you pass an object by value, the object's copy constructor is automatically invoked. This is often unnecessary and can have an enormous impact upon your program's performance and memory consumption, especially with complex object's that contain embedded objects and/or inherit from other classes, each of which must be copied. However, there will be occasions where a function needs to modify an object where those changes would be undesirable. Thus passing by value would be deemed acceptable. The alternative would be to manually copy your object and then pass the copy by reference or by pointer instead.
Pass the object by reference to a function in the DLL.
Lazy copying is a hybrid of the standard shallow-copy and deep-copy mechanisms. Objects that are copy constructed or assigned from existing instances will initially be shallow-copied, meaning their dynamic data members will share the same memory. When an object is mutated whilst sharing memory, its data will be deep copied so as not to affect the shared instances. In other words, deep-copying is postponed until it is actually required (if at all). For large and complex objects, this can offer a significant memory saving and a major performance boost as a shallow copy is significantly faster than a deep copy, and sharing memory obviously consumes less memory. In order to implement lazy copying, it is necessary for each instance to be fully aware of all the instances it shares memory with. One of the simplest ways of achieving that is for each instance to maintain bi-directional pointers, similar to those you would find in a doubly-linked list. However, unlike a linked list, there is no need to expose these pointers outside of the class as the class can link and unlink all by itself, via the copy constructor and the assignment operator. All the functionality is encapsulated within the class so the lazy copy mechanism is completely transparent to the end user. The following implementation provides a brief demonstration of how the mechanism works. It is by no means a complete implementation as it can only handle one type of data, but it serves to demonstrate the key aspects of lazy copying. A more complete implementation would change the data to a template class, thus allowing any type of data to be lazy copied. The output shows that while each instance of the object occupies separate memory locations, the data they contain is initially shared. We then manipulate the objects to show that deep copying is occurring when it is required, and that destroying a share doesn't affect any remaining shares. If you strip away the trace code in the main function you will see that the lazy copy mechanism is completely transparent; you need never know it exists as it is fully encapsulated within the Object class itself. // Demonstration of a lazy copy mechanism // Copyright ©PCForrest, 2012 #include <iostream> using namespace std; // Example data container. class Data { friend ostream& operator<<(ostream& os, const Data& data); public: inline ~Data(){delete(m_num);} inline Data():m_num(new int(0)){} inline Data(const int num):m_num(new int(num)){} inline Data(const Data& data):m_num(new int(*data.m_num)){} inline Data& operator=(const Data& data){*m_num=*data.m_num; return(*this);} inline Data& operator=(const int num){*m_num=num; return(*this);} inline bool operator==(const Data& data){return(*m_num==*data.m_num);} inline bool operator!=(const Data& data){return(*m_num!=*data.m_num);} inline int operator+(const Data& data){return(*m_num+*data.m_num);} inline int operator+(const int num){return(*m_num+num);} inline Data& operator+=(const Data& data){*m_num+=*data.m_num; return(*this);} inline Data& operator+=(const int num){*m_num+=num; return(*this);} inline int GetNum()const{return(*m_num);} inline void SetNum(const int num){*m_num=num;} private: int * m_num; }; // Friend function ostream& operator<<(ostream& os, const Data& data) { os<<"Data:0x"<<&data<<" ("<<*data.m_num<<")"; return(os); } // Lazy copy class. class Object { friend ostream& operator<<(ostream& os, const Object& object); public: inline Object():m_nextshare(NULL),m_prevshare(NULL),m_data(new Data(0)){} inline Object(const Object& object):m_prevshare(&object.LocateLastShare()),m_nextshare(NULL),m_data(object.m_data){m_prevshare->m_nextshare=this;} inline ~Object(){if(IsShared())UnlinkShare();else delete( m_data ); m_data = NULL;} Object& operator=(const Object& object); Object& operator+=(const Object& object); inline Data GetData()const{return( *m_data);} void SetData(const Data& data); private: inline bool IsShared()const{return(m_prevshare!=NULL m_nextshare!=NULL);} Object& LocateLastShare()const; Object* LocateShare(const Object & object)const; void UnlinkShare(); mutable Object * m_nextshare; mutable Object * m_prevshare; Data * m_data; }; // Friend function ostream& operator<<(ostream& os, const Object& object) { os<<"Object:0x"<<&object<<"\t"<<*object.m_data; return(os); } // Assign (implements shallow-copy) Object& Object::operator=(const Object& object) { if( &object != this && // Not a self-reference. !LocateShare(object) ) // Not already shared. { // Unlink or destroy data. if( IsShared() ) UnlinkShare(); else if( m_data ) delete( m_data ); // Shallow-copy. m_data = object.m_data; // Link to new shares. m_prevshare = &object.LocateLastShare(); m_prevshare->m_nextshare = this; } return(*this); } // Add/assign (implements deep-copy) Object& Object::operator+=(const Object& object) { if( IsShared() ) { UnlinkShare(); m_data = new Data( *m_data + *object.m_data ); } else *m_data += *object.m_data; return( *this ); } // Returns a reference to the last shared instance of this instance. Object& Object::LocateLastShare()const { Object* p=(Object*)this; while(p && p->m_nextshare) p=p->m_nextshare; return(*p); } // Returns a pointer to the given object if it is amongst the shared instances // of this instance. Returns NULL if the object is this instance or is not shared. Object* Object::LocateShare(const Object& object)const { // Search previous instances first. Object* p=m_prevshare; while( p && p!=&object) p=p->m_prevshare; if(!p) { // Not found, search next instances: p = m_nextshare; while( p && p!=&object) p=p->m_nextshare; } return(p); } // Unlinks this object from its shared instances. void Object::UnlinkShare() { // Update the links on either side first. if(m_nextshare) m_nextshare->m_prevshare=m_prevshare; if(m_prevshare) m_prevshare->m_nextshare=m_nextshare; m_nextshare=NULL; m_prevshare=NULL; } // Mutator. Implements deep copy if incoming data differs. void Object::SetData(const Data& data) { if( *m_data != data ) { if( IsShared() ) { UnlinkShare(); m_data = new Data(data); } else *m_data = data; } } // Demonstration program: int main() { Object a; a.SetData( 5 ); Object b = a; // Assign (lazy copy) Object* c = new Object(b); // Copy construct (lazy copy) cout<<"Original memory:"<<endl; cout<<"a\t"<<a<<endl; cout<<"b\t"<<b<<endl; cout<<"c\t"<<*c<<endl; cout<<endl; b += a; // Deep copy. cout<<"After mutating b:"<<endl; cout<<"a\t"<<a<<endl; cout<<"b\t"<<b<<endl; cout<<"c\t"<<*c<<endl; cout<<endl; delete(c); cout<<"After destroying c:"<<endl; cout<<"a\t"<<a<<endl; cout<<"b\t"<<b<<endl; cout<<endl; // Instantiate a new, unshared instance c = new Object(); cout<<"After instantiating c as new:"<<endl; cout<<"a\t"<<a<<endl; cout<<"b\t"<<b<<endl; cout<<"c\t"<<*c<<endl; cout<<endl; // Assign b to c *c = b; cout<<"After reassigning c:"<<endl; cout<<"a\t"<<a<<endl; cout<<"b\t"<<b<<endl; cout<<"c\t"<<*c<<endl; cout<<endl; return(0); } Output: Original memory: a Object:0x001FFA20 Data:0x003577B8 (5) b Object:0x001FFA0C Data:0x003577B8 (5) c Object:0x00211F58 Data:0x003577B8 (5) After mutating b: a Object:0x001FFA20 Data:0x003577B8 (5) b Object:0x001FFA0C Data:0x00357818 (10) c Object:0x00211F58 Data:0x003577B8 (5) After destroying c: a Object:0x001FFA20 Data:0x003577B8 (5) b Object:0x001FFA0C Data:0x00357818 (10) After instantiating c as new: a Object:0x001FFA20 Data:0x003577B8 (5) b Object:0x001FFA0C Data:0x00357818 (10) c Object:0x00211F58 Data:0x003578A8 (0) After reassigning c: a Object:0x001FFA20 Data:0x003577B8 (5) b Object:0x001FFA0C Data:0x00357818 (10) c Object:0x00211F58 Data:0x00357818 (10)
As string-literal: const char head [] = "<H1>Example</H1>";
struct rectangle { private: int top, bottom, left, right; public: int get_width()const{return(right-left);} int get_height()const{return(bottom-top);} int get_perimeter()const{return((get_width()+get_height())*2);} }
Use the address-of operator (&). Note that the function must accept a pointer to the class type. If it accepts a reference or value then you cannot pass the object's address, you must pass the object itself.
No. Constructors initialise objects and, by definition, must be able to modify the member variables. Uninitialised members are a disaster waiting to happen even without a constructor declared const! Thankfully, the compiler won't permit a const constructor.