Memory usage in dart lists - list

I've recently learned that lists in Dart will work like pointers such that
final List<int> a = [1,2,3,4]
final List<int> b = a;
b[1] = 5;
print(a);
print(b);
Will output the following
[1,5,3,4]
[1,5,3,4]
If you had a bit of code where
List<int> a = [1,2,3,4];
final List<int> b = List.from(A);
a = b;
Would you have stranded the memory at the address a was originally assigned to, or would Dart know to delete this, when b is pointed to the memory address of b?

Related

SFML returning Vertex array [duplicate]

I am fairly new to C++ and have been avoiding pointers. From what I've read online I cannot return an array but I can return a pointer to it. I made a small code to test it and was wondering if this was the normal / correct way to do this:
#include <iostream>
using namespace std;
int* test (int in[5]) {
int* out = in;
return out;
}
int main() {
int arr[5] = {1, 2, 3, 4, 5};
int* pArr = test(arr);
for (int i = 0; i < 5; i++) cout<<pArr[i]<<endl;
cout<<endl;
return 0;
}
Edit: This seems to be no good. How should I rewrite it?
int* test (int a[5], int b[5]) {
int c[5];
for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
int* out = c;
return out;
}
Your code as it stands is correct but I am having a hard time figuring out how it could/would be used in a real world scenario. With that said, please be aware of a few caveats when returning pointers from functions:
When you create an array with syntax int arr[5];, it's allocated on the stack and is local to the function.
C++ allows you to return a pointer to this array, but it is undefined behavior to use the memory pointed to by this pointer outside of its local scope. Read this great answer using a real world analogy to get a much clear understanding than what I could ever explain.
You can still use the array outside the scope if you can guarantee that memory of the array has not be purged. In your case this is true when you pass arr to test().
If you want to pass around pointers to a dynamically allocated array without worrying about memory leaks, you should do some reading on std::unique_ptr/std::shared_ptr<>.
Edit - to answer the use-case of matrix multiplication
You have two options. The naive way is to use std::unique_ptr/std::shared_ptr<>. The Modern C++ way is to have a Matrix class where you overload operator * and you absolutely must use the new rvalue references if you want to avoid copying the result of the multiplication to get it out of the function. In addition to having your copy constructor, operator = and destructor, you also need to have move constructor and move assignment operator. Go through the questions and answers of this search to gain more insight on how to achieve this.
Edit 2 - answer to appended question
int* test (int a[5], int b[5]) {
int *c = new int[5];
for (int i = 0; i < 5; i++)
c[i] = a[i]+b[i];
return c;
}
If you are using this as int *res = test(a,b);, then sometime later in your code, you should call delete []res to free the memory allocated in the test() function. You see now the problem is it is extremely hard to manually keep track of when to make the call to delete. Hence the approaches on how to deal with it where outlined in the answer.
Your code is OK. Note though that if you return a pointer to an array, and that array goes out of scope, you should not use that pointer anymore. Example:
int* test (void)
{
int out[5];
return out;
}
The above will never work, because out does not exist anymore when test() returns. The returned pointer must not be used anymore. If you do use it, you will be reading/writing to memory you shouldn't.
In your original code, the arr array goes out of scope when main() returns. Obviously that's no problem, since returning from main() also means that your program is terminating.
If you want something that will stick around and cannot go out of scope, you should allocate it with new:
int* test (void)
{
int* out = new int[5];
return out;
}
The returned pointer will always be valid. Remember do delete it again when you're done with it though, using delete[]:
int* array = test();
// ...
// Done with the array.
delete[] array;
Deleting it is the only way to reclaim the memory it uses.
New answer to new question:
You cannot return pointer to automatic variable (int c[5]) from the function. Automatic variable ends its lifetime with return enclosing block (function in this case) - so you are returning pointer to not existing array.
Either make your variable dynamic:
int* test (int a[5], int b[5]) {
int* c = new int[5];
for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
return c;
}
Or change your implementation to use std::array:
std::array<int,5> test (const std::array<int,5>& a, const std::array<int,5>& b)
{
  std::array<int,5> c;
  for (int i = 0; i < 5; i++) c[i] = a[i]+b[i];
  return c;
}
In case your compiler does not provide std::array you can replace it with simple struct containing an array:
struct array_int_5 {
int data[5];
int& operator [](int i) { return data[i]; }
int operator const [](int i) { return data[i]; }
};
Old answer to old question:
Your code is correct, and ... hmm, well, ... useless. Since arrays can be assigned to pointers without extra function (note that you are already using this in your function):
int arr[5] = {1, 2, 3, 4, 5};
//int* pArr = test(arr);
int* pArr = arr;
Morever signature of your function:
int* test (int in[5])
Is equivalent to:
int* test (int* in)
So you see it makes no sense.
However this signature takes an array, not pointer:
int* test (int (&in)[5])
A variable referencing an array is basically a pointer to its first element, so yes, you can legitimately return a pointer to an array, because thery're essentially the same thing. Check this out yourself:
#include <assert.h>
int main() {
int a[] = {1, 2, 3, 4, 5};
int* pArr = a;
int* pFirstElem = &(a[0]);
assert(a == pArr);
assert(a == pFirstElem);
return 0;
}
This also means that passing an array to a function should be done via pointer (and not via int in[5]), and possibly along with the length of the array:
int* test(int* in, int len) {
int* out = in;
return out;
}
That said, you're right that using pointers (without fully understanding them) is pretty dangerous. For example, referencing an array that was allocated on the stack and went out of scope yields undefined behavior:
#include <iostream>
using namespace std;
int main() {
int* pArr = 0;
{
int a[] = {1, 2, 3, 4, 5};
pArr = a; // or test(a) if you wish
}
// a[] went out of scope here, but pArr holds a pointer to it
// all bets are off, this can output "1", output 1st chapter
// of "Romeo and Juliet", crash the program or destroy the
// universe
cout << pArr[0] << endl; // WRONG!
return 0;
}
So if you don't feel competent enough, just use std::vector.
[answer to the updated question]
The correct way to write your test function is either this:
void test(int* a, int* b, int* c, int len) {
for (int i = 0; i < len; ++i) c[i] = a[i] + b[i];
}
...
int main() {
int a[5] = {...}, b[5] = {...}, c[5] = {};
test(a, b, c, 5);
// c now holds the result
}
Or this (using std::vector):
#include <vector>
vector<int> test(const vector<int>& a, const vector<int>& b) {
vector<int> result(a.size());
for (int i = 0; i < a.size(); ++i) {
result[i] = a[i] + b[i];
}
return result; // copy will be elided
}
In a real app, the way you returned the array is called using an out parameter. Of course you don't actually have to return a pointer to the array, because the caller already has it, you just need to fill in the array. It's also common to pass another argument specifying the size of the array so as to not overflow it.
Using an out parameter has the disadvantage that the caller may not know how large the array needs to be to store the result. In that case, you can return a std::vector or similar array class instance.
Your code (which looks ok) doesn't return a pointer to an array. It returns a pointer to the first element of an array.
In fact that's usually what you want to do. Most manipulation of arrays are done via pointers to individual elements, not via pointers to the array as a whole.
You can define a pointer to an array, for example this:
double (*p)[42];
defines p as a pointer to a 42-element array of doubles. A big problem with that is that you have to specify the number of elements in the array as part of the type -- and that number has to be a compile-time constant. Most programs that deal with arrays need to deal with arrays of varying sizes; a given array's size won't vary after it's been created, but its initial size isn't necessarily known at compile time, and different array objects can have different sizes.
A pointer to the first element of an array lets you use either pointer arithmetic or the indexing operator [] to traverse the elements of the array. But the pointer doesn't tell you how many elements the array has; you generally have to keep track of that yourself.
If a function needs to create an array and return a pointer to its first element, you have to manage the storage for that array yourself, in one of several ways. You can have the caller pass in a pointer to (the first element of) an array object, probably along with another argument specifying its size -- which means the caller has to know how big the array needs to be. Or the function can return a pointer to (the first element of) a static array defined inside the function -- which means the size of the array is fixed, and the same array will be clobbered by a second call to the function. Or the function can allocate the array on the heap -- which makes the caller responsible for deallocating it later.
Everything I've written so far is common to C and C++, and in fact it's much more in the style of C than C++. Section 6 of the comp.lang.c FAQ discusses the behavior of arrays and pointers in C.
But if you're writing in C++, you're probably better off using C++ idioms. For example, the C++ standard library provides a number of headers defining container classes such as <vector> and <array>, which will take care of most of this stuff for you. Unless you have a particular reason to use raw arrays and pointers, you're probably better off just using C++ containers instead.
EDIT : I think you edited your question as I was typing this answer. The new code at the end of your question is, as you observer, no good; it returns a pointer to an object that ceases to exist as soon as the function returns. I think I've covered the alternatives.
you can (sort of) return an array
instead of
int m1[5] = {1, 2, 3, 4, 5};
int m2[5] = {6, 7, 8, 9, 10};
int* m3 = test(m1, m2);
write
struct mystruct
{
int arr[5];
};
int m1[5] = {1, 2, 3, 4, 5};
int m2[5] = {6, 7, 8, 9, 10};
mystruct m3 = test(m1,m2);
where test looks like
struct mystruct test(int m1[5], int m2[5])
{
struct mystruct s;
for (int i = 0; i < 5; ++i ) s.arr[i]=m1[i]+m2[i];
return s;
}
not very efficient since one is copying it delivers a copy of the array

best practice to select and modify entries in nested vectors

I'm looking for an efficient way to solve the following (presumably easy) problem:
I have a vector of type A.
Class A contains a vector of type B.
There is no way that I can change class A or the design of
the vector of class A (I cannot make it a vector of pointers to A
for example).
I want to have a vector of class B which contains all entries of B contained in the vector of A with a special attribute.
I guess it is a bit complicated to read about the problem but probably easier to understand if you see an example:
#include <vector>
#include <iostream>
using namespace std;
struct B {
int n;
double val;
};
struct A {
vector<B> v;
};
int main() {
// generate some dummy data:
A a1;
a1.v.push_back(B{1, 1.0});
a1.v.push_back(B{2, 2.0});
a1.v.push_back(B{1, 3.5});
A a2;
a1.v.push_back(B{2, 2.0});
a1.v.push_back(B{3, 1.0});
a1.v.push_back(B{1, 2.5});
// this is my initial situation: a vector of type A
vector<A> va;
va.push_back(a1);
va.push_back(a2);
// what I want to get is a vector of type B with all B values whose n == 1
vector<B> vb;
// possible solution to get all elements of B
for(auto &any : va){
for(auto &b : any.v){
if(b.n == 1){
vb.push_back(b);
}
}
}
for(const auto &any:vb){
cout << any.val << endl;
}
return 0;
}
Questions:
I would like to get the vector of class B without copying every element. Later, I need to modify the elements in vector B and they should also be modified in vector A (meaning, if I change vb[0].val = 100; the entry in va[0].v[0] should also be 100;
I thought about using pointers to do this but I am unsure if it is a good idea since the elements of vector va are allocated on the stack and not on the heap.
** Edit: **
I can ensure that as soon as I need the vector of B I will not modify the vector of A in any way.
Having va on the stack is not necessarily a problem, as long as you move va to its new location. In that case your "moved to" vector will internally point to the storage allocated by your "moved from" va vector (and the original va will become empty).
What is an issue though, is if you add new Bs to an A after having already created pointers to Bs. If the A's v vector does not have enough capacity to store the newly inserted B, it will have to reallocate all its B elements to a new storage location. That in turn will change the addresses of all of those B elements.
Thus, you are fine to create pointers as long as you can guarantee that:
va is moved instead of copied.
No new Bs are added to an A after initialization.
Assuming the above can be guaranteed, you can create your vb as follows:
std::vector<B *> vb;
for (auto & a : va) {
for (auto & b : a.v) {
if (b.n == 1) { vb.push_back(&b); }
}
}
or using std::reference_wrapper:
std::vector<std::reference_wrapper<B>> vb;
for (auto & a : va) {
std::copy_if(a.v.begin(), a.v.end(),
std::back_inserter(vb),
[](auto const & b) { return b.n == 1; });
}

C++ exception on array deletion

I am making 2 Arrays a and b
Then I try to assign a to b and after that I get exception at delete[] b, why?
void main()
{
int a[5] = {1, 2, 3, 4, 5};
int *b = new int[3];
b = a;
delete[] b;
}
For starters b is not an array. It is a pointer. After this statement
b = a;
two things occurred. The first one is that the address of the dynamically allocated array
int *b = new int[3];
was lost.
And the second one is that the pointer b now points to the first elements of the array a that was not allocated dynamically with using the operator new. So you may not apply the operator delete to the pointer b in this case.
I think you mean copying elements of the array a into the dynamically allocated array pointed to by the pointer b.
In this case instead of the statement
b = a;
you should write
#include <algorithm>
//...
std::copy( a, a + 3, b );
//...
delete [] b;
Bear in mind that according to the C++ Standard the function main without parameters shall be declared like
int main()
Here is a demonstrative program.
#include <iostream>
#include <algorithm>
int main()
{
int a[5] = { 1, 2, 3, 4, 5 };
size_t n = 3;
int *b = new int[n];
std::copy( a, a + n, b );
for (size_t i = 0; i < n; i++ ) std::cout << b[i] << ' ';
std::cout << std::endl;
delete [] b;
std::cin.get();
return 0;
}
What you new[]-ed is not what you pass to delete[]. After having the b = a, the b pointer no longer points to first (original) array element. You need to pass in the original pointer:
int* b = new int[3];
int* originalb = b;
// your other code in here
delete[] originalb;
That being said don't assign the dynamically allocated b to a.
When you do b = a, it means that the pointer that's called b, points to the content of a, which is allocated on the stack.
When you attempt to delete it, it would obviously fail.

Is operator< (less than) on pointers consistent?

Note: This question is not about total order. A total order on pointers of the same type can be obtained using std::less.
According to this, comparing two pointers with operator< isn't allowed if they point for example into different allocations.
In which sense isn't it allowed? Is it implementation defined, unspecified or undefined behaviour?
I think I read somewhere that it's unspecified. An implementation isn't required to document what the behaviour is, but there must be some behaviour. So that would mean, comparing any two pointers is still legal, but doesn't neccessarily yield a total order. Does that mean, that we still have to get a consistent result, when comparing the same two pointers twice? The general case would be: Does invoking the same unspecified behaviour twice within an application always yield the same result?
int i1, i2;
int* a = &i1;
int* b = &i2;
bool b1 = a < b; // unspecified, right?
bool b2 = a < b;
assert(b1 == b2); // Is this guaranteed to be true?
Comparing two unrelated pointers (i.e. pointers not pointing to the same memory, or not pointing to different parts of the same "array") can only be done using equality == and inequality !=. All other comparison is unspecified.
If you have two pointers pointing to the same place, or inside the same array, then you can compare them using the relative operators.
So if you have e.g.
int* p1 = new int[10];
int* p2 = new int[5];
you can only use == and != to compare the pointers p1 and p2.
But if you have
int a = new int[10];
int* p1 = &a[0];
int* p2 = &a[3];
then you can use also < and > (and of course <= and >=) to compare p1 and p2
It is not possible to compare two unrelated pointers(except using == and !=), that is comparing two unrelated pointer is undefined.
However, it is still possible to create a vector of pointers and then sort that vector in terms of the address of those pointers! See example 2 below.
Example 1:
int a = 5,b = 6;
int *a_ptr = &a, *b_ptr = &b;
bool ans = a_ptr < b_ptr;//undefined behavior
Example 2:
#include <iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
std::string firstName = "Anoop",middleName = "Singh", lastName = "Rana";
std::vector<string *> storage_ptr = {&firstName,&middleName,&lastName};
std::vector<string *>::iterator begin = storage_ptr.begin();
while(begin!=storage_ptr.end()){
std::cout<<(**begin)<<std::endl;
begin++;
}
std::sort(storage_ptr.begin(),storage_ptr.end(),greater<string *>());
std::vector<string *>::iterator begin2 = storage_ptr.begin();
while(begin2!=storage_ptr.end()){
std::cout<<(**begin2)<<std::endl;
begin2++;
}
return 0;
}
As you can see that the first while loop prints the vector in descending order while the second while loop prints the vector in ascending order showing that using the new standard we can use the function object greater<string *> to sort the vector of pointers.
Comparing pointers as shown in your example makes little sense because "a" and "b" value depends on how is the data stored in memory, not on the content stored in that location.
Pointers are addresses in memory (usually stored as 32 bit integer). Unless you change any of them, their comparison will return the same result. You might not know what that result is, but you'll know that it'll be the same every time.
Therefore, in your case, you will get the same result for both b1 and b2, so the assertion will pass.
Here is an example where comparing pointers does make sense:
int data[1000];
int *end = data + 50;
for (int *c = data; c < end; c++)
... use *c

Change the value of elements in the array by pointers - vector<int> C++ [duplicate]

This question already has answers here:
C++ trying to swap values in a vector
(5 answers)
Closed 9 years ago.
I use Visual Studio 2012. I've created my own function which works like sprintf(&a).
And i need to resolve problem: how do I swap two specific pointer elements?
Here is my code:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
void swap_spec(vector<int>* a, vector<int>* b)
{
vector<int>* tmp = NULL;
*tmp = *a;
*a = *b;
*b = *tmp;
}
int main()
{
vector<int> test(4);
test[0] = 5;
test[1] = 4;
test[2] = 3;
test[3] = 2;
swap_spec(*test[0], *test[1]);
printf("%d %d", test[0], test[1]);
return 0;
}
I got an error:
terminate called after throwing an instance of 'std::bad_alloc'
what(): std::bad_alloc
What is wrong? What i should change?
I am unsure as to what you are trying to do, but I am going to guess you are trying to swap two values in a vector. As your comments have said, using the swap would work, but I think you are confused as to what your code actually does. Let's go step by step here:
vector<int> test(4);
test[0] = 5;
test[1] = 4;
test[2] = 3;
test[3] = 2;
swap_spec(*test[0], *test[1]); // *test[0] is the same as *(test[0])
When you perform *test[0], this is the same as *(test[0]). This means to dereference/look at the value in memory address test[0], which is 5. That memory address is inaccessible for you, so it will cause a seg fault.
Second problem:
void swap_spec(vector<int>* a, vector<int>* b)
{
vector<int>* tmp = NULL;
*tmp = *a;
*a = *b; // This says, get whatever vector is pointed at b, and copy it to the memory location variable a points to.
*b = *tmp;
}
Since you are passing in pointers to vectors, what you're saying here is to swap the two vectors, not the values inside them. But when you call this with:
swap_spec(*test[0], *test[1]);
The type of test[0] is an int, the type of *(test[0]) is a dereferenced int (which is a seg-fault, but supposedly another int type), but the parameter type is a vector * (a pointer to a vector), which is already inconsistent with the arguments you pass in. See how this is already wrong in multiple levels.
So given all those information, it looks like you are trying to swap two values in the vector. You can do this one of two ways. You can do this with pointers:
void swap_spec(int *a, int *b) {
int tmp = *a;
*a = *b; // Go to address location where variable a points to, and assign whatever value is at memory location where variable b points to
*b = tmp;
}
swap_spec(&test[0], &test[1]); // Pass in address of where test[0] and test[1] points to
// Note that type of &test[0] is an int * (Consistent with parameter)
Or with references:
void swap_spec(int &a, int &b) {
int tmp = a;
a = b; // Since you are using references, this will actually modify test[0] at its memory location
b = tmp;
}
swap_spec(test[0], test[1]); // Since you are using references, you don't need to pass in the address.
The second way is the same as the standard library's swap (http://www.cplusplus.com/reference/algorithm/swap/). References are sometimes (or perhaps generally) favored because it produces cleaner code (less * operators used) and hence less confusion.
You declare your function to take pointers to vector<int>s as parameters but you then pass is something else. *test[1] is dereferencing test[1] which is the int 4. You are treating ints 4 and 5 as pointers which is problematic.
It is not entirely clear what you are trying to accomplish, but if you just want to swap two elements of a vector, why not something like:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
void swap_spec(vector<int> & a, size_t i, size_t j)
{
int tmp;
tmp = a[i];
a[i] = a[j];
a[j] = tmp;
}
int main()
{
vector<int> test(4);
test[0] = 5;
test[1] = 4;
test[2] = 3;
test[3] = 2;
printf("%d %d \n", test[0], test[1]);
swap_spec(test, 0, 1);
printf("%d %d \n", test[0], test[1]);
return 0;
}
Suppose what you really want do to is to swap two specific pointer elements. Then there are few possible errors. First the vector you created is an integer array instead of an pointer vector:
vector<int> test(4);
Second, in your function interface, the types of your input parameters are in fact a pointer to an integer vector (which means you would like to swap two vectors, instead of two integer pointers).
void swap_spec(vector<int>* a, vector<int>* b)
Third, since your vector is an integer vector, applying the indirection Operator * will let you get an error (*a means give me the content stored in the memory location described in variable a).
swap_spec(*test[0], *test[1]);
The following is how to swap "two integer pointers":
#include <stdio.h>
void swap_spec(int** a, int** b) // the function which swaps int pointers.
{
int** tmp;
*tmp = *a;
*a = *b;
*b = *tmp;
}
int main()
{
int** test = new int*[4]; // create an array of int integers
for (int i = 0; i < 4; ++i) {
test[i] = new int;
}
*test[0] = 5;
*test[1] = 4;
*test[2] = 3;
*test[3] = 2;
printf("%d %d\n", *test[0], *test[1]);
swap_spec(&test[0], &test[1]); // pass their addresses instead
printf("%d %d\n", *test[0], *test[1]);
for (int i = 0; i < 4; ++i) {
delete test[i];
}
delete[] test;
return 0;
}
If what you would like to do is simply swapping two int elements in a vector, then std::swap() or the answers proposed by #Narfanator and #Spook should work.
Alright, I think this should do you, but my C's a little rusty:
#include <iostream>
#include <stdio.h>
#include <vector>
using namespace std;
void swap_spec(int* a, int* b)
{
int tmp = NULL;
tmp = *a;
*a = *b;
*b = tmp;
}
int main()
{
vector<int> test(4);
test[0] = 5;
test[1] = 4;
test[2] = 3;
test[3] = 2;
swap_spec(&test[0], &test[1]);
printf("%d %d", test[0], test[1]);
return 0;
}
What I have done here is "swap the values at two memory locations", and then passed in the locations of the first and second element of your vector.
Let's go over your code, see if we can't clear some of what's going on up:
void swap_spec(vector<int>* a, vector<int>* b)
This says: Give me two pointers to vectors storing ints. When you're dealing with the elements of a vector, you just pass around the type stored in the vector: in this case, int:
void swap_spec(int a, int b)
However, C/C++ are pass-by-value, which means the passed values would be copied, and then used locally - meaning, you could not effect the overal program environment by passing in the values.
You got this, which is why you passed in pointers.
Instead, you need to pass in pointers to the values:
void swap_spec(int* a, int* b)
Technically, you're passing-by-value a memory address. Anyway - This lets you interact with memory (and this variables, objects, etc) outside of the function, in the overal program.
swap_spec(*test[0], *test[1]);
This passes in the values stored at the memory locations stored in test[0], which is invalid, because it's five.
What you want is:
swap_spec(&test[0], &test[1]);
Which pass in the memory addresses of those values, which is what you wanted.
I guess, that you want to swap elements inside the vectors, not the vectors themselves. So firstly, don't swap std::vector<int> *, but just int *.
Secondly, pointers are not needed here at all. Use a function:
void swap_spec(std::vector<int> & vec, int index1, int index2)
{
int tmp = vec[index1];
vec[index1] = vec[index2];
vec[index2] = tmp;
}
Then call it like this:
swap_spec(test, 0, 1);