473,769 Members | 6,739 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

STL Question: Safe to use elements after erasing them from the collection?

To settle the dispute regarding what happens when an "erase" method is
invoked on an STL container (i.e. whether the element is merely
removed from the container or whether it also gets deleted in the
process), I looked up the STL code. Erase certainly does not delete
the memory associated with the element. However, it appears that the
destructor on the element is invoked. I wonder why it has to be this
way. In my opinion, this renders the element extremely risky to use
after it has been "erased" from the collection.
stl_list.h
....
iterator erase(iterator position) {
link_type next_node = link_type(posit ion.node->next);
link_type prev_node = link_type(posit ion.node->prev);
prev_node->next = next_node;
next_node->prev = prev_node;
destroy_node(po sition.node);
return iterator(next_n ode);
}
....

void destroy_node(li nk_type p) {
destroy(&p->data);
put_node(p);
}
....
stl_construct.h
....
template <class T>
inline void destroy(T* pointer) {
pointer->~T(); // KPB Note:- we are explicitly
// invoking the destructor,
// but we are not performing
// the delete operation
}
....
Any insights into this would be welcome.

Regards,
KP Bhat
Jul 22 '05 #1
8 2214
"Generic Usenet Account" <us****@sta.sam sung.com> wrote in message
news:90******** *************** *@posting.googl e.com...
| To settle the dispute regarding what happens when an "erase" method is
| invoked on an STL container (i.e. whether the element is merely
| removed from the container or whether it also gets deleted in the
| process), I looked up the STL code.
| Erase certainly does not delete the memory associated with the element.
Most containers (excluding std::vector) may release the memory associated
with items that have been removed using the erase member function.
However, many implementations will keep a cache of previously
allocated nodes, to speed-up later addition of new elements.

| However, it appears that the
| destructor on the element is invoked. I wonder why it has to be this
| way. In my opinion, this renders the element extremely risky to use
| after it has been "erased" from the collection.
According to the standard, the destructor of the erased elements
*must* be called. It is not uncommon for code to rely on the
deterministic destruction of the items being erased.
Attempting to access items that have been erased leads to undefined
behavior. Even if they were not destroyed immediately, hopefully
the memory they occupy would be recycled at some point. So it
wouldn't be safe to access the erased items either way.

| void destroy_node(li nk_type p) {
| destroy(&p->data);
| put_node(p);
| }
I would guess that 'put_node()' is used by this implementation
to store the node into a list of nodes that can be recycled.

| stl_construct.h
| ...
| template <class T>
| inline void destroy(T* pointer) {
| pointer->~T(); // KPB Note:- we are explicitly
| // invoking the destructor,
| // but we are not performing
| // the delete operation
| }
The allocated memory includes the item itself and the
prev/next links of the list nodes. It may also be part
of an array of nodes that have been allocated as a chunk,
to optimize performance.
The memory storage itself will typically be freed or
recycled at a later point in time...
I hope this helps,
Ivan
--
http://ivan.vecerina.com/contact/?subject=NG_POST <- e-mail contact form
Brainbench MVP for C++ <> http://www.brainbench.com
Jul 22 '05 #2
Generic Usenet Account wrote:
To settle the dispute regarding what happens when an "erase" method is
invoked on an STL container (i.e. whether the element is merely
removed from the container or whether it also gets deleted in the
process), I looked up the STL code. Erase certainly does not delete
the memory associated with the element. However, it appears that the
destructor on the element is invoked. I wonder why it has to be this
way. In my opinion, this renders the element extremely risky to use
after it has been "erased" from the collection. ....
Any insights into this would be welcome.


From the perspective of the container's client, you don't know if a
delete or calling the destructor is used and you should not know.

I suspect that the container is using a caching mechanism to speed up
the case where objects are destroyed and re-created in succession. But
the client should not care.

Jul 22 '05 #3
"Ivan Vecerina" <pl************ *****@ivan.vece rina.com> wrote in message
news:bq******** **@newshispeed. ch...
"Generic Usenet Account" <us****@sta.sam sung.com> wrote in message
news:90******** *************** *@posting.googl e.com...
| To settle the dispute regarding what happens when an "erase" method is
| invoked on an STL container (i.e. whether the element is merely
| removed from the container or whether it also gets deleted in the
| process), I looked up the STL code.
| Erase certainly does not delete the memory associated with the element.
Most containers (excluding std::vector) may release the memory associated
with items that have been removed using the erase member function. <<snip>> According to the standard, the destructor of the erased elements
*must* be called. It is not uncommon for code to rely on the
deterministic destruction of the items being erased.
Attempting to access items that have been erased leads to undefined
behavior. Even if they were not destroyed immediately, hopefully
the memory they occupy would be recycled at some point. So it
wouldn't be safe to access the erased items either way.


Does this mean that it is bad behavior to put an object into two different
containers, or is that even possible?
(Forgive me for asking, but in Java it works differently. I was hoping it
worked similarly in C++.)
--
Gary
Jul 22 '05 #4
Gary Labowitz wrote:
Does this mean that it is bad behavior to put an object into two
different containers, or is that even possible?
(Forgive me for asking, but in Java it works differently. I was
hoping it worked similarly in C++.)


It would seem to be me that the object being destructed is the list *node*
that contains the object you put in it, not the actual object. The latter
would be impossible, because it can be an intrinsic type (that has no
destructor to call) or a pointer or copied object or whatever. And in the
case of pointers, it's not the list's responsibility to take care of object
lifetime anyway. That's always the responsibility of whoever called new.

--
Unforgiven

"Most people make generalisations "
Freek de Jonge
Jul 22 '05 #5
In article <z5************ ********@comcas t.com>,
Gary Labowitz <gl*******@comc ast.net> wrote:

Does this mean that it is bad behavior to put an object into two different
containers, or is that even possible?


It's not even possible. When you "put an object into a container", you
are actually putting a *copy* of the object into the container, invoking
the copy constructor of the object's class.

To prevent the copying, you can store a *pointer* to the object into a
suitably-declared container (e.g. vector<foo*> instead of vector<foo>),
but in that case, erasing the pointer has no effect on the object itself.

--
Jon Bell <jt*******@pres by.edu> Presbyterian College
Dept. of Physics and Computer Science Clinton, South Carolina USA
Jul 22 '05 #6
"Jon Bell" <jt*******@pres by.edu> wrote in message
news:bq******** **@jtbell.presb y.edu...
In article <z5************ ********@comcas t.com>,
Gary Labowitz <gl*******@comc ast.net> wrote:

Does this mean that it is bad behavior to put an object into two differentcontainers, or is that even possible?


It's not even possible. When you "put an object into a container", you
are actually putting a *copy* of the object into the container, invoking
the copy constructor of the object's class.

To prevent the copying, you can store a *pointer* to the object into a
suitably-declared container (e.g. vector<foo*> instead of vector<foo>),
but in that case, erasing the pointer has no effect on the object itself.


Ah, so. And, of course. Java operates only like the latter (only it's a
reference variable). No problem. Thanks.
--
Gary
Jul 22 '05 #7
jt*******@presb y.edu (Jon Bell) wrote in message news:<bq******* ***@jtbell.pres by.edu>...
It's not even possible. When you "put an object into a container", you
are actually putting a *copy* of the object into the container, invoking
the copy constructor of the object's class.

To prevent the copying, you can store a *pointer* to the object into a
suitably-declared container (e.g. vector<foo*> instead of vector<foo>),
but in that case, erasing the pointer has no effect on the object itself.

Jon Bell is absolutely right. I am attaching some source code that I
wrote to test out the STL behavior with this posting. My apologies if
I am breaking the netiquette of this group.

Here are my findings....

· If the collection stores values rather than pointers (e.g.
list<Class_XYZ> ), a copy of the entity is dynamically created, using
the copy constructor, and stored in the collection

· If the collection stores pointers rather than values (e.g. list<
Class_XYZ*>), the entity itself is stored

· If the collection stores values rather than pointers, upon invoking
erase(), the copy of the entity (that was stored in the collection)
gets deleted (using delete, since the destructor gets invoked). The
original entity is left untouched

· If the collection stores pointers rather than values, upon invoking
erase(), the entity is merely removed from the collection but does not
get deleted
In other words....
1) erase() merely removes an element from a collection, and does not
free up the associated memory

2) If the entity is an object, it is copied with the copy constructor
and deleted with the destructor.

3) If the entity is a pointer, the pointer is copied by value and the
storage for the pointer is subsequently released. Releasing the
pointer does not affect the pointed-to object.
Regards,
KP Bhat
//~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ ~Element.h~~~~~ ~~~~~~~~~~~~~~~ ~~~~~~~
#include <time.h>
#include <iostream.h>

class Element
{
public:
Element(time_t i, char x[])
{
m_attr = i;
strcpy(m_label, x);

cout << "CTOR:: Element " << dec << m_attr << ", Pointer " << hex
<< this << ", " << m_label << endl;

}

Element(const Element& elem)
{
m_attr = elem.m_attr;
strcpy(m_label, elem.m_label);

cout << "COPY-CTOR:: Element " << dec << m_attr << ", Pointer " <<
hex
<< this << ", " << m_label << endl;
}

~Element()
{
cout << "DTOR:: Element " << dec << m_attr << ", Pointer " << hex
<< this << ", " << m_label << endl;
}

void display()
{
cout << ctime(&m_attr);
}

void printAddress() const
{
cout << hex << this << endl;
}

bool operator<(const Element& elem) const
{
bool retVal = (m_attr < elem.m_attr);
return retVal;
}

protected:
time_t m_attr;
char m_label[80];
};
//~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~ ~Main.cpp~~~~~~ ~~~~~~~~~~~~~~~ ~~~~~~
#include "Element.h"

#ifdef VECTOR
#include <vector>
#elif defined LIST
#include <list>
#elif defined DEQUE
#include <deque>
#elif defined SET
#include <set>
#elif defined MULTISET
#include <multiset.h>
#endif
void
main()
{
#ifdef VECTOR
cout << "Vector test\n\n";
#elif defined LIST
cout << "List test\n\n";
#elif defined DEQUE
cout << "Deque test\n\n";
#elif defined SET
cout << "Set test\n\n";
#elif defined MULTISET
cout << "Multiset test\n\n";
#endif

Element elem1(132, "VALUE");
Element elem2(232, "VALUE");
Element elem3(332, "VALUE");

Element *elem4 = new Element(432, "POINTER");
Element *elem5 = new Element(532, "POINTER");
Element *elem6 = new Element(632, "POINTER");

Element elem7(732, "VALUE --- will store address in Ptr
collection");
Element elem8(832, "VALUE --- will store address in Ptr
collection");
Element elem9(932, "VALUE --- will store address in Ptr
collection");

Element *elem10 = &elem7;
Element *elem11 = &elem8;
Element *elem12 = &elem9;

cout << endl;

#ifdef VECTOR
vector<Element> collElem;
vector<Element* > collElemPtr;

vector<Element> ::iterator valueItor;
vector<Element* >::iterator pointerItor;

cout << "Inserting elements in collection-1\n";
collElem.push_b ack(elem1);
collElem.push_b ack(elem2);
collElem.push_b ack(elem3);
cout << "Inserted elements in collection-1\n\n";

cout << "Inserting elements in collection-2\n";
collElemPtr.pus h_back(elem4);
collElemPtr.pus h_back(elem5);
collElemPtr.pus h_back(elem6);
collElemPtr.pus h_back(elem10);
collElemPtr.pus h_back(elem11);
collElemPtr.pus h_back(elem12);
cout << "Inserted elements in collection-2\n\n";

#elif defined LIST
list<Element> collElem;
list<Element*> collElemPtr;

list<Element>:: iterator valueItor;
list<Element*>: :iterator pointerItor;

cout << "Inserting elements in collection-1\n";
collElem.push_b ack(elem1);
collElem.push_b ack(elem2);
collElem.push_b ack(elem3);
cout << "Inserted elements in collection-1\n\n";

cout << "Inserting elements in collection-2\n";
collElemPtr.pus h_back(elem4);
collElemPtr.pus h_back(elem5);
collElemPtr.pus h_back(elem6);
collElemPtr.pus h_back(elem10);
collElemPtr.pus h_back(elem11);
collElemPtr.pus h_back(elem12);
cout << "Inserted elements in collection-2\n\n";

#elif defined DEQUE
deque<Element> collElem;
deque<Element*> collElemPtr;

deque<Element>: :iterator valueItor;
deque<Element*> ::iterator pointerItor;

cout << "Inserting elements in collection-1\n";
collElem.push_b ack(elem1);
collElem.push_b ack(elem2);
collElem.push_b ack(elem3);
cout << "Inserted elements in collection-1\n\n";

cout << "Inserting elements in collection-2\n";
collElemPtr.pus h_back(elem4);
collElemPtr.pus h_back(elem5);
collElemPtr.pus h_back(elem6);
collElemPtr.pus h_back(elem10);
collElemPtr.pus h_back(elem11);
collElemPtr.pus h_back(elem12);
cout << "Inserted elements in collection-2\n\n";

#elif defined SET
set<Element> collElem;
set<Element*> collElemPtr;

set<Element>::i terator valueItor;
set<Element*>:: iterator pointerItor;

cout << "Inserting elements in collection-1\n";
collElem.insert (elem1);
collElem.insert (elem2);
collElem.insert (elem3);
cout << "Inserted elements in collection-1\n\n";

cout << "Inserting elements in collection-2\n";
collElemPtr.ins ert(elem4);
collElemPtr.ins ert(elem5);
collElemPtr.ins ert(elem6);
collElemPtr.ins ert(elem10);
collElemPtr.ins ert(elem11);
collElemPtr.ins ert(elem12);
cout << "Inserted elements in collection-2\n\n";
#elif defined MULTISET
multiset<Elemen t> collElem;
multiset<Elemen t*> collElemPtr;

multiset<Elemen t>::iterator valueItor;
multiset<Elemen t*>::iterator pointerItor;

cout << "Inserting elements in collection-1\n";
collElem.insert (elem1);
collElem.insert (elem2);
collElem.insert (elem3);
cout << "Inserted elements in collection-1\n\n";

cout << "Inserting elements in collection-2\n";
collElemPtr.ins ert(elem4);
collElemPtr.ins ert(elem5);
collElemPtr.ins ert(elem6);
collElemPtr.ins ert(elem10);
collElemPtr.ins ert(elem11);
collElemPtr.ins ert(elem12);
cout << "Inserted elements in collection-2\n\n";
#endif
cout << "\n\nTraver sing collElem collection (collection-1)" << endl;
for(valueItor = collElem.begin( ); valueItor != collElem.end();
valueItor++)
{
cout << "The object pointer is ";
valueItor->printAddress() ;
}
cout << "Traversed collElem collection (collection-1)" << endl;

cout << "\n\nTraver sing collElemPtr collection (collection-2)" <<
endl;
for(pointerItor = collElemPtr.beg in(); pointerItor !=
collElemPtr.end ();
pointerItor++)
{
Element* elemPtr = *pointerItor;
cout << "The object pointer is ";
elemPtr->printAddress() ;
}
cout << "Traversed collElemPtr collection (collection-2)" << endl;
cout << "\n\nErasin g collElem collection (collection-1)" << endl;
collElem.erase( collElem.begin( ), collElem.end()) ;
cout << "Erased collElem (collection-1) entirely\n\n" << endl;

cout << "\n\nErasin g collElemPtr collection (collection-2)" << endl;
collElemPtr.era se(collElemPtr. begin(), collElemPtr.end ());
cout << "Erased collElemPtr (collection-2) entirely\n\n" << endl;

return 0;
}
Jul 22 '05 #8
us****@sta.sams ung.com (Generic Usenet Account) wrote in message news:<90******* *************** ***@posting.goo gle.com>...

Here are my findings....

· If the collection stores values rather than pointers (e.g.
list<Class_XYZ> ), a copy of the entity is dynamically created, using
the copy constructor, and stored in the collection

· If the collection stores pointers rather than values (e.g. list<
Class_XYZ*>), the entity itself is stored

· If the collection stores values rather than pointers, upon invoking
erase(), the copy of the entity (that was stored in the collection)
gets deleted (using delete, since the destructor gets invoked). The
original entity is left untouched

· If the collection stores pointers rather than values, upon invoking
erase(), the entity is merely removed from the collection but does not
get deleted
In other words....
1) erase() merely removes an element from a collection, and does not
free up the associated memory

2) If the entity is an object, it is copied with the copy constructor
and deleted with the destructor.

3) If the entity is a pointer, the pointer is copied by value and the
storage for the pointer is subsequently released. Releasing the
pointer does not affect the pointed-to object.

For base classes with a virtual method, it is a safer bet to go with a
collection of pointers rather than a collection of instances, as the
following code snippet shows:

//~~~~~~~~~~~~~~~ ~~~~ Code snippet begins ~~~~~~~~~~
#include <iostream.h>
#include <list.h>

class Base
{
protected:
int i;

public:
Base(int m){ i = m;}
int get_i(){return i;}
virtual int xyz(){return i;} // Returns the value of the base
// class attribute
};

class Derived : public Base
{
protected:
int j;

public:
Derived(int m, int n):Base(m){j=n; }
int get_j(){return j;}
int xyz(){return j;} // Returns the value of the derived
// class attribute
};

typedef list<Base> BaseList;
typedef list<Base>::ite rator BaseIterator;
typedef list<Derived> DerivedList;
typedef list<Derived>:: iterator DerivedIterator ;

typedef list<Base*> BasePtrList;
typedef list<Base*>::it erator BasePtrIterator ;
typedef list<Derived*> DerivedPtrList;
typedef list<Derived*>: :iterator DerivedPtrItera tor;
main()
{
Derived *d[5];

for(int k1 = 0; k1 < 5; k1++)
{
d[k1] = new Derived(k1, 2*k1);
// The base attribute ('i') has value 0 through
4
// The derived attribute value ('j') is double
that
}

// Instance collection declarations
BaseList bcollection;
BaseIterator biter, beol;
DerivedList dcollection;
DerivedIterator diter, deol;
// Pointer collection declarations
BasePtrList bpcollection;
BasePtrIterator bpiter, bpeol;
DerivedPtrList dpcollection;
DerivedPtrItera tor dpiter, dpeol;

for(int k2 = 0; k2 < 5; k2++)
{
//Insert elements in base collection
bcollection.ins ert(bcollection .begin(), *d[k2]);

//Insert the SAME elements in the derived collection
dcollection.ins ert(dcollection .begin(), *d[k2]);

//Insert elements in base-ptr collection
bpcollection.in sert(bpcollecti on.begin(), d[k2]);

//Insert the SAME elements in the derived-ptr collection
dpcollection.in sert(dpcollecti on.begin(), d[k2]);
}

cout << "** Instance-collection behavior **\n";
// Iterate through the base collection and execute the
// virtual method "xyz()" on each element
cout << "Base collection:" << endl;
beol = bcollection.end ();
for(biter=bcoll ection.begin(); biter != beol; biter++)
cout << " get_i()=" << (*biter).get_i( ) << ", xyz()="
<< (*biter).xyz() << endl;

// Iterate through the derived collection and execute the
// virtual method "xyz()" on each element. Since we entered
// the exact same elements in both lists, the EXPECTED output
// is the same as before.
//
// Check out for yourself ;-(
//
cout << "Derived collection:" << endl;
deol = dcollection.end ();
for(diter=dcoll ection.begin(); diter != deol; diter++)
cout << " get_i()=" << (*diter).get_i( ) << ", xyz()="
<< (*diter).xyz() << endl;

cout << "The exact same elements were entered in both
collections.\n"
<< "Is the output the same in both the cases?\n";

cout << "\n\n** Pointer-collection behavior **\n";
// Iterate through the base-pointer collection and execute the
// virtual method "xyz()" on each element
cout << "Base-pointer collection:" << endl;
bpeol = bpcollection.en d();
for(bpiter=bpco llection.begin( ); bpiter != bpeol; bpiter++)
cout << " get_i()=" << (*bpiter)->get_i() << ", xyz()="
<< (*bpiter)->xyz() << endl;

// Iterate through the derived-pointer collection and execute the
// virtual method "xyz()" on each element. Since we entered
// the exact same elements in both lists, the EXPECTED output
// is the same as before.
//
// No surprises this time around :-(
cout << "Derived-pointer collection:" << endl;
dpeol = dpcollection.en d();
for(dpiter=dpco llection.begin( ); dpiter != dpeol; dpiter++)
cout << " get_i()=" << (*dpiter)->get_i() << ", xyz()="
<< (*dpiter)->xyz() << endl;

cout << "The exact same elements were entered in both
collections.\n"
<< "Is the output the same in both the cases?\n";

}

//~~~~~~~~~~~~~~~ ~~~~ Code snippet ends ~~~~~~~~~~

Regards,
KP Bhat
Jul 22 '05 #9

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

10
1713
by: Pat | last post by:
Hi, I use "vector<int> v" in my program. If "v" contains the following: (front) 1 2 3 4 2 5 7 1 (end), I want to remove some element, say "2", and I want the resultant "v" to be as follows: (front) 1 3 4 5 7 1 (end)
7
2145
by: Gui Lloyd | last post by:
I have a problem with performance in IE. The script above works quite fine when the table has a small number of elements, but, when the table has 2500 elements, when I click in the checkbox of the table header (to select all the checkboxes in table), the script demands at least 3 minutes to execute. I tested the same script in Mozilla and the response time is much more faster. Does anyone has an idea? <script> function...
3
7982
by: Grandma Wilkerson | last post by:
Hi, The documentation states that enumeration through a collection is inherently NOT thread-safe, since a thread which added/removed an item from said collection could screw up the thread that was iterating. That makes sense.. but... given a collection that is filled at start-time and never modified again, is it safe to have multiple threads *reading* (not writing to) the collection using foreach()? I have a class that exposes an...
6
3063
by: russ | last post by:
Hi, We have stumbled across an issue using the type safe collection System.Collections.ObjectModel.Collection <T> to retrieve data from our data layer. Say we have a customer object and want to get a type safe collection of all customers who have spend = X Within our datalayer we would currently have the following method
6
1771
by: Peter Oliphant | last post by:
I just discovered that the ImageList class can't be inherited. Why? What could go wrong? I can invision a case where someone would like to add, say, an ID field to an ImageList, possible so that the individual elements in an array of ImageList's could be identified by the ID, thereby allowing re-ordering the array without harm. A person could identify by index into the array, but that would not be preserved by re-ordering (and re-ordering...
10
5083
by: Piotr | last post by:
In Effective STL item 9 "Choose carefully among erasing options", it has this example: bool badValue(int x); // returns whether x is 'bad' c.erase ( remove_if(c.begin(), c.end(), badValue), c.end()); // this is the best way to get rid of objects where badValue returns true when c is a vector, string, or dequeue c.remove_if(badValue); // this is the best way to get rid of objects where badValue returns true when c is a list
34
2613
by: Mathieu Trentesaux | last post by:
Hello I downloaded Office 2007 for this reason : It seems, once again, that it is impossible to save any modification done in a VBA library, from the main project in Access. The save button remains desperatly grayed. It also seems impossible to open the library in another Access instance
6
3141
by: fniles | last post by:
I am using VB.NET 2003 and a socket control to receive and sending data to clients. As I receive data in 1 thread, I put it into an arraylist, and then I remove the data from arraylist and send it to the client. Before adding data to the arraylist, I check if the depth of the arraylist is longer than iMaxQueueDepth, and if it is, I clear the arraylist. Is it possible that while I am clearing the arraylist, the ThreadMain at the same time...
10
6076
by: arnuld | last post by:
WANTED: /* C++ Primer - 4/e * * Exercise: 9.26 * STATEMENT * Using the following definition of ia, copy ia into a vector and into a list. Use the single iterator form of erase to remove the elements with odd values from your list * and the even values from your vector.
0
10216
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. Here is my compilation command: g++-12 -std=c++20 -Wnarrowing bit_field.cpp Here is the code in...
1
9997
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For most users, this new feature is actually very convenient. If you want to control the update process,...
0
9865
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each protocol has its own unique characteristics and advantages, but as a user who is planning to build a smart home system, I am a bit confused by the choice of these technologies. I'm particularly interested in Zigbee because I've heard it does some...
0
8873
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing, and deployment—without human intervention. Imagine an AI that can take a project description, break it down, write the code, debug it, and then launch it, all on its own.... Now, this would greatly impact the work of software developers. The idea...
0
6675
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert into image. Globals.ThisAddIn.Application.ActiveDocument.Select();...
0
5310
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in the same network. But I'm wondering if it's possible to do the same thing, with 2 Pfsense firewalls...
0
5448
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
3965
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
2
3565
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.