Construct one list from element of another list without adding to heap memory

Related searches

I am developing a memory critical application. I first generate a list, for example (C++11):

std::list<string> nodes({"Hello","Welcome", "Hi", "World"});

I need to now create a smaller list with the second and third elements of 'nodes.' Naively, I would do:

std::list<string> sub_nodes;
sub_nodes.push_back(*std::next(nodes.begin(),1));
sub_nodes.push_back(*std::next(nodes.begin(),2));

But this clearly allocates memory in the heap for sub_nodes by allocating new memory.

*(sub_nodes.begin()) = "NotWelcome"; //changing first element
std::list<string>::iterator it;
for(it=nodes.begin();it!=nodes.end();++it) cout<<*it<<'\t';
cout<<'\n';
//Hello Welcome Hi World
for(it=sub_nodes.begin();it!=sub_nodes.end();++it)
cout<<*it<<'\t';
cout<<'\n';
//NotWelcome Hi

What I wish to accomplish is to have the elements of sub_nodes occupy the same address of the elements of nodes from which they were created. In other words, I want the changes made to elements of sub_nodes reflected in those elements in nodes and vice versa. In C linked lists, this would be straight forward since the list nodes are basically pointers. How would I accomplish the same in C++?

You can use std::reference_wrapper, which works as a reference and is able to be stored in a container.

std::list<std::reference_wrapper<std::string>> sub_nodes; // #include <functional>

Note although std::reference_wrapper has an implicit conversion operator to its value type, sometimes you still have to use its explicit get method. For example, you have to use

(*sub_nodes.begin()).get() = "NotWelcome"; 

to change the referenced object.

The following is a full working example:

#include <iostream>
#include <functional>
#include <list>
#include <string>

int main()
{
    std::list<std::string> nodes({"Hello","Welcome", "Hi", "World"});
    std::list<std::reference_wrapper<std::string>> sub_nodes;
    sub_nodes.push_back(*std::next(nodes.begin(), 1));
    sub_nodes.push_back(*std::next(nodes.begin(), 2));
    (*sub_nodes.begin()).get() = "NotWelcome"; 
    for (auto it = nodes.begin(); it != nodes.end(); ++it) std::cout << *it << '\t';
    std::cout << '\n';
    // Hello NotWelcome Hi World
    for (auto it = sub_nodes.begin(); it != sub_nodes.end(); ++it)
        std::cout << (*it).get() << '\t';
    std::cout << '\n';
    // NotWelcome Hi
}

Merge K sorted linked lists, Given K sorted linked lists of size N each, merge them and print the sorted output. Merged lists in a sorted order where every element is greater than is to use Min Heap based solution which is discussed here for arrays. The idea is to pair up K lists and merge each pair in linear time using O(1) space. Once you add the first element to the list, a real, unique elementData array is created, and the provided object is inserted into it. To avoid resizing the array every time a new element is added

A std::list<T> owns its elements. Thats one major motivation for using std containers. They manage the lifetime of their elements. If you want the container to not own its elements then don't make it store Ts. There are several options. With std::list you have the advantage that std::lists iterators do not get invalidated that easily (eg std::vector may reallocate and copy all elements on each insert, not the case for std::list). Hence, you could use iterators:

std::list< std::list<std::string>::iterator > sub_nodes;
sub_nodes.push_back( nodes.begin() );
// etc..

Just be careful that if nodes invalidates its iterators, eg by erasing an element, then sub_nodes may contain invalid entries.

Merge k sorted linked lists, Given k sorted linked lists each of size n, merge them and print the sorted output. Mapping the elements of a heap into an array is trivial: if a node is 'compare' function used to build up the Utility function to create a new node (Using Merge Sort) � In-place Merge two linked lists without changing links� But you should remember, that all these ways will give you a copy of your List, not all of its elements. So if you change one of the elements in your copied List, it will also be changed in your original List.

You can create a list of string pointers.

std::list<std::string*> slist1;

slist1.push_back(new std::string("Hello"));
slist1.push_back(new std::string("Welcome"));
slist1.push_back(new std::string("Hi"));
slist1.push_back(new std::string("World"));

Then create another list using the same pointers.

auto it = slist1.begin();
std::list<std::string*> slist2(std::next(it, 1), std::next(it, 3));

This slist2 list pointers are the same pointers as in slist1. Now changing any pointer will get reflected at both the places. For example, below code replace "Welcome" and "Hi" in slist2 with "abc". Changes are reflected in slist1 too as the pointers are same.

for (auto &s: slist2) {
        std::cout << *s << "\n";
       *s = "abc";
 }

for (auto &s: slist1) {
        std::cout << *s << " "; //prints Hello abc abc World
    }

Please note that this code is not exception safe and the list would have to be deleted manually. For exception safety and automatic destruction, please use smart pointers. Below is an example using shared_ptr.

#include <iostream>
#include <memory>
#include <string>
#include <list>
int main()
{
    std::list<std::shared_ptr<std::string>> slist1;

    slist1.push_back(std::make_shared<std::string>("Hello"));
    slist1.push_back(std::make_shared<std::string>("Welcome"));
    slist1.push_back(std::make_shared<std::string>("Hi"));
    slist1.push_back(std::make_shared<std::string>("World"));

    auto it = slist1.begin();
    std::list<std::shared_ptr<std::string>> slist2(std::next(it, 1), std::next(it, 3));
    for (auto &s: slist2) {
        std::cout << *s << " ";
        *s = "abc";
    }

    for (auto &s: slist1)
        std::cout << *s << " ";  //prints Hello abc abc World
    return 0;
}

How to Prevent Your Java Collections From Wasting Memory, Once you add the first element to the list, a real, unique elementData array is Next, most collection objects contain the size field, a pointer to the internal array or another situations where the heap is full of 0-, 1- or 2-element collections. And without knowing exactly where the memory goes, you may� A simple way to copy a List is by using the constructor that takes a collection as its argument:. List<Plant> copy = new ArrayList<>(list); Due to the fact that we're copying reference here and not cloning the objects, every amends made in one element will affect both lists.

Heaps, The heap property is repaired by comparing the added element with its parent 1) doubleSize(); //Insert a new item to the end of the array int pos = ++size; 1. build a heap 1, 2, 4, 5, 3, 6 2. turn this heap into a sorted list deleteMin 1, 2, 4, 5, 3 ,� Dynamic Memory Allocation Examples using C programs 1) C program to create memory for int, char and float variable at run time.. In this program we will create memory for int, char and float variables at run time using malloc() function and before exiting the program we will release the memory allocated at run time by using free() function.

10 ways to Join two Lists in Java, In this post, we will see how to join two lists in Java using Plain Java, Java 8, Guava and Apache Commons Collections 1. List.addAll() List interface provides addAll(Collection) method that appends all elements of the specified factory method Stream.of() and accumulating all elements into a new list using a Collector. A list can be copied using the = operator. For example, old_list = [1, 2, 3] new_list = old_list. The problem with copying lists in this way is that if you modify new_list, old_list is also modified.

ArrayList add() method is used to add an element in the list. We can add elements of any type in arraylist, but make program behave in more predicatable manner, we should add elements of one certain type only in any goven list instance. Use generics for compile time type safety while adding the element to arraylist. 1. ArrayList add() syntax

Comments
  • also in c++ you can use pointers, though smart pointers are preferable
  • This is the question. How would I add elements to a std::list by reference?
  • Unrelated to your question, but are you sure std::list is the best container for you? What are you using it for? What are the requirement that leads you to use a list over the default container std::vector? And if memory is critical, note that a std::list of X nodes uses more memory than a std::vector of X elements (because of the private node structures themselves). Perhaps you should use a std::deque instead (to get a little of both lists and vectors)?
  • @Someprogrammerdude because there is a possibility of data insertion, in my application.
  • You want to splice the list?
  • Would this approach work for other objects or structs other than std::string ?
  • Yes I think it should as we are using pointers(in this case it is string type but it can be other type too)
  • Please use smart pointers, otherwise the code is not exception safe and you have to manually delete those strings before the list is destructed. Also, *s = "abc" is enough for changing a string. std::string is mutable in C++.
  • You have undefined behaviour here. You are derefencing pointers that were invalidated by a previous delete. It so happens that your implementation used the same addresses for the string allocations that were just released.
  • @Caleth - i don't think it is undefined behaviour. Pointer is not being dereferenced after deletion. IMHO delete ptr; ptr = new something; is not undefined behaviour. *ptr would have been undefined, but after allocation ptr points to a valid memory.