I have a void* pointer p that points to an array of data whose type is T (mostly float), I want to update data using this pointer p, so I cast it with reinterpret_cast<T*>(p) and then modify the values. The problem is, p itself must not be modified, so for safety I really want to cast it to T* const, but I don't know how to do it properly.
T* const cp = reinterpret_cast<T* const>(p);
T* const cp = static_cast<T* const>(p);
T* const cp = static_cast<T* const>(reinterpret_cast<T*>(p));
....
I know the easiest way is to make a copy of p and use that copied pointer instead, so that the original p never gets modified, just wonder how I can achieve the same thing by casting.
Casting a pointer will create a new pointer value which is separate and distinct from the old one. p will not be affected, period. So there's no need to play around with const here.
Related
In Dart, looking at the code below, does it 'pass by reference' for list and 'pass by value' for integers? If that's the case, what type of data will be passed by reference/value? If that isn't the case, what's the issue that causes such output?
void main() {
var foo = ['a','b'];
var bar = foo;
bar.add('c');
print(aoo); // [a, b, c]
print(bar); // [a, b, c]
var a = 3;
int b = a;
b += 2;
print(a); // 3
print(b); // 5
}
The question your asking can be answered by looking at the difference between a value and a reference type.
Dart like almost every other programming langue makes a distinction between the two. The reason for this is that you divide memory into the so called stack and the heap. The stack is fast but very limited so it cannot hold that much data. (By the way, if you have too much data stored in the stack you will get a Stack Overflow exception which is where the name of this site comes from ;) ). The heap on the other hand is slower but can hold nearly infinite data.
This is why you have value and reference types. The value types are all your primitive data types (in Dart all the data type that are written small like int, bool, double and so on). Their values are small enough to be stored directly in the stack. On the other hand you have all the other data types that may potentially be much bigger so they cannot be stored in the stack. This is why all the other so called reference types are basically stored in the heap and only an address or a reference is stored in the stack.
So when you are setting the reference type bar to foo you're essentially just copying the storage address from bar to foo. Therefore if you change the data stored under that reference it seems like your changing both values because both have the same reference. In contrast when you say b = a your not transferring the reference but the actual value instead so it is not effected if you make any changes to the original value.
I really hope I could help answering your question :)
In Dart, all type are reference types. All parameters are passed by value. The "value" of a reference type is its reference. (That's why it's possible to have two variables containing the "same object" - there is only one object, but both variables contain references to that object). You never ever make a copy of an object just by passing the reference around.
Dart does not have "pass by reference" where you pass a variable as an argument (so the called function can change the value bound to the variable, like C#'s ref parameters).
Dart does not have primitive types, at all. However (big caveat), numbers are always (pretending to be) canonicalized, so there is only ever one 1 object in the program. You can't create a different 1 object. In a way it acts similarly to other languages' primitive types, but it isn't one. You can use int as a type argument to List<int>, unlike in Java where you need to do List<Integer>, you can ask about the identity of an int like identical(1, 2), and you can call methods on integers like 1.hashCode.
If you want to clone or copy a list
var foo = ['a', 'b'];
var bar = [...foo];
bar.add('c');
print(bar); // [a, b, c]
print(foo); // [a, b]
var bar_two = []; //or init an empty list
bar_two.addAll([...bar]);
print(bar_two); // [a, b, c]
Reference link
Clone a List, Map or Set in Dart
For the past few days am trying to learn if pass by value and pass by reference impact the memory differently. Googling this query, people kept repeating themselves about a copy being created in terms of pass by value and how the original value is affected in terms pass by reference. But I was wondering if someone could zero in on the memory part.
This question actually depends heavily on the particular language as some allow you to be explicit and define when you want to pass a variable by value and when by reference and some do it always the same way for different types of variables.
A quite popular type of behavior is to use passing by value (by default) for simple times: like int, string, long, float, double, bool etc.
Let us show the memory impact on a theoretical language:
int $myVariable = 5;
at this moment you have created a one variable in memory which takes the size required to store an integer (let us say 32 bits).
Now you want to pass it to a function:
function someFunction(int parameter)
{
printOnScreen(parameter);
}
so your code would look like:
function someFunction(int $parameter)
{
printOnScreen($parameter);
}
int $myVariable = 5; //Position A
someFunction($myVariable); //Position B
...rest of the code //Position C
Since simple types are passed by value the value is copied in memory to another storage place - therefore:
during Position A you have memory occupied by ONE int (with value 5);
during Position B you have memory occupied by TWO ints (with values of 5) as your $myVariable was copied in memory
during Position C you have again memory occupied by ONE int (with value of 5) as the second one was already destroyed as it was needed only for the time of execution of the function
This has some other implications: modifications on a variable passed by value DO NOT affect the original variable - for example:
function someFunction(int $parameter)
{
$parameter = $parameter + 1;
printOnScreen($parameter);
}
int $myVariable = 5; //Position A
someFunction($myVariable); //Position B
printOnScreen($myVariable); //Position C
During position A you set value of 5 under variable $myVariable.
During position B you pass it BY VALUE to a function which adds 1 to your passed value. YET since it was a simple type, passed by value, it actually operates on a LOCAL variable, a COPY of your variable. Therefore position C will again write just 5 (your original variable as it was not modified).
Some languages allow you to be explicit and inform that you want to pass a reference and not the value itself using a special operator -for example &. So let us again follow the same example but with explicit info that we want a reference (in function's arguments
- note the &):
function someFunction(int &$parameter)
{
$parameter = $parameter + 1;
printOnScreen($parameter);
}
int $myVariable = 5; //Position A
someFunction($myVariable); //Position B
printOnScreen($myVariable); //Position C
This time operation and memory implications will be different.
During Position A an int is created (every variable is always consisted of two elements: place in memory and a pointer, an identifier which place is it. For ease of the process let us say that pointer is always one byte). So whenever you create a variable you actually create two things:
reserved place in memory for the VALUE (in this case 32 bits as it was an int)
pointer (8 bits [1 byte])
Now during position B, the function expects A POINTER to a memory place. Which means that it will locally, for itself create only a copy of the pointer (1 byte) and not copy the actual reserved place as the new pointer WILLL POINT to the same place as the original one. This means that during operation of the function you have:
TWO POINTERS to an int in memory
ONE place reserved for VALUE of the int
Both of those pointer POINT to the same VALUE
Which means that any modification of the value will affect both.
So looking at the same example position C will not print out also 6 as inside the function we have modified the value under the SAME POINTER as $myVariable.
For COMPLEX TYPES (objects) the default action in most programming environments is to pass the reference (pointer).
So for example - if you have a class:
class Person {
public string $name;
}
and create an instance of it and set a value:
$john = new Person();
$john->name = "John Malkovic";
and later pass it to a function:
function printName(Person $instanceOfPerson)
{
printOnScreen($instanceOfPerson);
}
in terms of memory it will again create only a new POINTER in memory (1 byte) which points to the same value. So having a code like this:
function printName(Person $instanceOfPerson)
{
printOnScreen($instanceOfPerson);
}
$john = new Person(); // position A
printName($john); // position B
...rest of the code // position C
during position A you have: 1 Person (which means 1 pointer [1 byte] to a place in memory which has size to store an object of class person)
during position B you have: 2 pointers [2 bytes] but STILL one place in memory to store an object of class person's value [instance]
during position C you have again situation from position A
I hope that this clarifies the topic for you - generally there is more to cover and what I have mentioned above is just a general explanation.
Pass-by-value and pass-by-reference are language semantics concepts; they don't imply anything about the implementation. Usually, languages that have pass-by-reference implement it by passing a pointer by value, and then when you read or write to the variable inside the function, the compiler translates it into reading or writing from a dereference of the pointer. So you can imagine, for example, if you have a function that takes a parameter by reference in C++:
struct Foo { int x; }
void bar(Foo &f) {
f.x = 42;
}
Foo a;
bar(a);
it is really syntactic sugar for something like:
struct Foo { int x; }
void bar(Foo *f_ptr) {
(*f_ptr).x = 42;
}
Foo a;
bar(&a);
And so passing by reference has the same cost as passing a pointer by value, which does involve a "copy", but it's the copy of a pointer, which is a few bytes, regardless of the size of the thing pointed to.
When you talk about pass-by-value doing a "copy", that doesn't really tell you much unless you know what exactly the variable or value passed represents in the language. For example, Java only has pass-by-value. But every type in Java is either a primitive type or a reference type, and the values of reference types are "reference", i.e. pointers to objects. So you can never have a value in Java (what a variable holds or what an expression evaluates to) which "is" an "object"; objects in Java can only be manipulated through these "references" (pointers to objects). So when you ask the cost of passing a object in Java, it's actually wrong because you cannot "pass" an object in Java; you can only pass references (pointers to objects), and the copy the happens for pass-by-value, is the copy of the pointer, which is a few bytes.
So the only case where you would actually copy a big structure when passing, is if you have a language where objects or structs are values directly (not behind a reference), and you do pass-by-reference of that object/struct type. So for example, in C++, you can have objects which are values directly, or you can have pointers to them, and you can pass them by value or by reference:
struct Foo { int x; }
void bar1(Foo f1) { } // pass Foo by value; this copies the entire size of Foo
void bar2(Foo *f2) { } // pass pointer by value; this copies the size of a pointer
void bar3(Foo &f3) { } // pass Foo by reference; this copies the size of a pointer
void bar4(Foo *&f4) { } // pass pointer by reference; this copies the size of a pointer
(Of course, each of those have different semantic meanings; for example, the last one allows the code inside the function to modify the pointer variable passed to point to somewhere else. But if you are concerned about the amount copied. Only the first one is different. In Java, effectively only the second one is possible.)
In the Rust Book there is an example of calling filter() on an iterator:
for i in (1..100).filter(|&x| x % 2 == 0) {
println!("{}", i);
}
There is an explanation below but I'm having trouble understanding it:
This will print all of the even numbers between one and a hundred. (Note that because filter doesn't consume the elements that are being iterated over, it is passed a reference to each element, and thus the filter predicate uses the &x pattern to extract the integer itself.)
This, however does not work:
for i in (1..100).filter(|&x| *x % 2 == 0) {
println!("i={}", i);
}
Why is the argument to the closure a reference |&x|, instead of |x|? And what's the difference between using |&x| and |x|?
I understand that using a reference |&x| is more efficient, but I'm puzzled by the fact that I didn't have to dereference the x pointer by using *x.
When used as a pattern match (and closure and function arguments are also pattern matches), the & binds to a reference, making the variable the dereferenced value.
fn main() {
let an_int: u8 = 42;
// Note that the `&` is on the right side of the `:`
let ref_to_int: &u8 = &an_int;
// Note that the `&` is on the left side of the `:`
let &another_int = ref_to_int;
let () = another_int;
}
Has the error:
error: mismatched types:
expected `u8`,
found `()`
If you look at your error message for your case, it indicates that you can't dereference it, because it isn't a reference:
error: type `_` cannot be dereferenced
I didn't have to dereference the x pointer by using *x.
That's because you implicitly dereferenced it in the pattern match.
I understand that using a reference |&x| is more efficient
If this were true, then there would be no reason to use anything but references! Namely, references require extra indirection to get to the real data. There's some measurable cut-off point where passing items by value is more efficient than passing references to them.
If so, why does using |x| not throw an error? From my experience with C, I would expect to receive a pointer here.
And you do, in the form of a reference. x is a reference to (in this example) an i32. However, the % operator is provided by the trait Rem, which is implemented for all pairs of reference / value:
impl Rem<i32> for i32
impl<'a> Rem<i32> for &'a i32
impl<'a> Rem<&'a i32> for i32
impl<'a, 'b> Rem<&'a i32> for &'b i32
This allows you to not need to explicitly dereference it.
Or does Rust implicitly allocate a copy of value of the original x on the stack here?
It emphatically does not do that. In fact, it would be unsafe to do that, unless the iterated items implemented Copy (or potentially Clone, in which case it could also be expensive). This is why references are used as the closure argument.
Have this function defined in your module:
module Data
int inc(x) = x + 1;
Type this in the console:
rascal> import Data;
rascal> import List;
This works:
rascal> inc(1);
int: 2
But this does not:
rascal> list[int] y = [1,2,3];
rascal> mapper(y, inc);
|rascal://<path>|: insert into collection not supported on value and int
☞ Advice
But it works if inc(...)'s parameter type is declared:
int inc(int x) = x + 1;
So why does not having this type declaration work for using the inc(...) function directly, but not for passing that function to mapper(...)?
Because Rascal's type checker is still under development, you are not warned if you make a small mistake like forgetting to provide a type for a function parameter. It may still work, accidentally, in some circumstances but you are guaranteed to run into trouble somewhere as you've observed. The reason is that type inference for function parameters is simply not implemented as a feature. This is a language design decision with the intent of keeping error messages understandable.
So, this is not allowed:
int f(a) = a + 1;
And, it should be written like this:
int f(int a) = a + 1;
I consider it a bug that the interpreter doesn't complain about an untyped parameter. It is caused by the fact that we reuse the pattern matching code for both function parameters and inline patterns. [edit: issue has been registered at https://github.com/cwi-swat/rascal/issues/763]
In your case the example works because dynamically the type of the value is int and addition does not check the parameter types. The broken example breaks because the interpreter does checks the type of the function parameter at the call-site (which defaulted to value for the untyped parameter).
I was curious to know if one could define a data type that we know, should be a tuple, but whose length (or number of elements is indeterminable) currently. The application is as follows:
//I want to declare a data type, one of whose argument is a tuple,
public data MyType=fromListCartesianProduct(tuple<?> product)
//Later I want to instantiate a MyType data by using taking List-CartesianProduct
//instantiate some MyType data
foreach(aTuple in [1,2,3]*["a","b"])
someArr[i]=fromListCartesianProduct(aTuple)
The salient observation is that the number of elements in aTuple is indeterminable while declaring "MyType". Can I still declare such a type in a rascal script?
As an alternate, I would declare MyType as:
public data MyType=fromListCartesianProduct(list[] product)
and convert each tuple from taking the cartesian product into a list before constructing the specific instances. For reasons of clarity and others, I would like to define MyType as I previously did.
In principe the answer is no. Tuples have fixed length and we do not (yet) have row polymorphism.
Having said that, data constructors do support different kinds of polymorphism which might help:
row polymorphism using keyword parameters, you can always add more keyword parameters to a data-type, as in
data MyType = myCons(int j = 0); // initial decl
data MyType(int k = 1); // extension with another field
overloading, you can always add more constructors with more parameters
data MyType = f(int i); // initial declaration
data MyType = f(int i, int j); // overloaded declaration with more fields
You might use the make function from Type to dynamically construct such constructors based on argument lists. At the risk of run-time type exceptions of course.
Another way of dealing with data of unpredictable type is to go up one level in the type hierarchy (let it be value), and later pattern match your way out again:
list[value] myListRelationOfUnknownType = ...;
for (<int i, int j> <- myListRelationOfUnknownType)
println("printing only pairs of ints: <i> - <j>");
for (<int i, int j, int k> <- myListRelationOfUnknownType)
println("printing only the triples of ints: <i> - <j> - <k>");
That's a statically more safe way.