I have a constant pointer cp that points to A and a non constant pointer p that points to B. I wold say that I can assign cp to p, i.e. p=cp because in this way both cp and p point to A and I cannot do the opposite: cp=p, because in this way I am saying that cp should point to B but cp is a constant pointer so I cannot change what it is pointing to.
I tried with this simple code but the result is the opposite, can someone explain me what is the correct version please?
std::vector<int> v;
v.push_back(0);
auto cp = v.cbegin(); // .cbegin() is constant
auto p = v.begin(); // .begin() is non constant
now if I write cp=p the compiler doesn't mark as error, but if I write p=cp the compiler marks the error.
cbegin is a pointer to something that is constant. You can change that pointer to point to something of the same constant type.
You're confusing this with a pointer, which is constant, to something that is not.
This is hard to see here, but the difference is between
const int* cp; // pointer to a constant value, but can point to something else
int* const pc; // pointer is constant, value can change
const int* const cpc; // pointer cannot be changed, value it points to cannot be changed
You can never make a "pointer that points to something that's not const" point at something that is const – because that means that you could change what is const, by derefencing the pointer!
const int value = 5; // can never change value
const int value2 = 10; // can never change value
const int* cp = &value; // our pointer to const int points at a const int
*cp = 6; // error: the value of something const can't be changed
cp = &value2; // fine, because we're pointing at a const int
int* p const = &value; // error: trying to point a pointer to non-const to a const, which would allow us to:
*p = 7; // which should be illegal.
Related
#include<stdio.h>
int main(){
int a, b, c;
char *p = 0;
int *q = 0;
double *r = 0;
cout<<(int)(p + 1); // printing 1 char size
cout<<(int)(q + 1); // printing 4
cout<<(int)(r + 1); // printing 8
int y = 9;
int *u = &y;
cout<<(int)(u+1); //printing 7208688
cout<<*(p+1); //not able to dereferance
}
How is type-casting working in both the above case?
Why pointers p, q, r are unable to dereference?
Dereferencing any of p, q, r, p + 1, q + 1, r + 1 or u + 1 has undefined behaviour, because none of those pointers point to objects of the correct type.
You can add to a pointer, to get a different pointer value. This is only defined for results that stay within the same array, plus the "one-past-the-end" pointer value (treating a pointer to a single object as an array of length one). You can also convert a pointer to an integer type, to get an implementation defined value. Doing those things does not involve dereferencing the pointer.
Adding to a null pointer is also undefined behaviour, because the null pointer does not point to an object, there is nothing to be "one-past-the-end" of.
I am trying to understand how to use Cuda in Java. I am using jCuda.
Everything was fine until I came across an example containing the code:
// Set up the kernel parameters: A pointer to an array
// of pointers which point to the actual values.
Pointer kernelParameters = Pointer.to(
Pointer.to(new int[]{numElements}),
Pointer.to(deviceInputA),
Pointer.to(deviceInputB),
Pointer.to(deviceOutput)
);
The kernel function prototype is:
__global__ void add(int n, float *a, float *b, float *sum)
The question is:
In terms of c, does it not seem that we are passing something like?
(***n, ***a, ***b, ***sum)
So basically, do we always have to have:
Pointer kernelParameters = Pointer.to( double pointer, double pointer, ...)???
Thank you
The cuLaunchKernel function of JCuda corresponds to the cuLaunchKernel function of CUDA. The signature of this function in CUDA is
CUresult cuLaunchKernel(
CUfunction f,
unsigned int gridDimX,
unsigned int gridDimY,
unsigned int gridDimZ,
unsigned int blockDimX,
unsigned int blockDimY,
unsigned int blockDimZ,
unsigned int sharedMemBytes,
CUstream hStream,
void** kernelParams,
void** extra)
where the kernelParams is the only parameter that is relevant for this question. The documentation says
Kernel parameters can be specified via kernelParams. If f has N parameters, then kernelParams needs to be an array of N pointers. Each of kernelParams[0] through kernelParams[N-1] must point to a region of memory from which the actual kernel parameter will be copied.
The key point here is the last sentence: The elements of the kernelParams array are not the actual kernel parameters. They only point to the actual kernel parameters.
And indeed, this has the odd effect that for a kernel that receives a single float *pointer, you could basically set up the kernel parameters as follows:
float *pointer= allocateSomeDeviceMemory();
float** pointerToPointer = &pointer;
float*** pointerToPointerToPointer = &pointerToPointer;
void **kernelParams = pointerToPointerToPointer;
(This is just to make clear that this is indeed a pointer to a pointer to a pointer - in reality, wou wouldn't write it like that)
Now, the "structure" of the kernel parameters is basically the same for JCuda and for CUDA. Of course you can not take "the address of a pointer" in Java, but the number of indirections is the same. Imagine you have a kernel like this:
__global__ void example(int value, float *pointer)
In the CUDA C API, you can then define the kernel parameters as follows:
int value = 123;
float *pointer= allocateSomeDeviceMemory();
int* pointerToValue = &value;
float** pointerToPointer = &pointer;
void **kernelParams = {
pointerToValue,
pointerToPointer
};
The setup is done analogously in the JCuda Java API:
int value = 123;
Pointer pointer= allocateSomeDeviceMemory();
Pointer pointerToValue = Pointer.to(new int[]{value});
float** pointerToPointer = Pointer.to(pointer);
Pointer kernelParameters = Pointer.to(
pointerToValue,
pointerToPointer
);
The main difference that is relevant here is that you can write this a bit more concisely in C, using the address operator &:
void **kernelParams = {
&value, // This can be imagined as a pointer to an int
&pointer // This can be imagined as a pointer to a pointer
};
But this is basically the same as in the example that you provided:
Pointer kernelParameters = Pointer.to(
Pointer.to(new int[]{value}), // A pointer to an int
Pointer.to(pointer) // A pointer to a pointer
);
Again, the key point is that with something like
void **kernelParams = {
&value,
};
or
Pointer kernelParameters = Pointer.to(
Pointer.to(new int[]{value}),
);
you are not passing the value to the kernel directly. Instead, you are telling CUDA: "Here is an array of pointers. The first pointer points to an int value. Copy the value from this memory location, and use it as the actual value for the kernel call".
In C++, I have a map < int, vector < double > > or map < int, vector < some_Struct > >, I need to concatenate the vectors in this map and return the result.
The first version of the function is below:
#include <algorithm>
#include <vector>
vector < double >
flattenRecords(const map < int, vector < double > > & selected, int num_kept_reps)
{
vector < double > records;
int cnt = 0;
for (auto it = selected.begin(); it != selected.end(); ++it) {
records.insert(records.end(),
make_move_iterator(it->second.begin()),
make_move_iterator(it->second.end()));
cnt += 1;
if (cnt >= num_kept_reps)
break;
}
return records;
}
I know this is not what I intended to do, because I would like to keep the data in the map, and thus should not use make_move_iterator.
The codes can compile using g++ (GCC) 4.4.7 with the -std=c++0x flag.
So here is the question, I declare the map to be const, what happens when I try to use something like std::move to the vector in the map?
My second version is to use:
copy(it->second.begin(), it->second.end(), back_inserter(records));
I guess this does what I intend to do.
I am quite new to C++. The STL gives me a feeling of coding in python so I would like to try it.
Instead of using make_move_iterator(Iterator), just use Iterator if you would not like to move the elements. Eg:
records.insert(records.end(), it->second.begin(), it->second.end());
Your second version, as you guess, does indeed what you try to achieve.
Regarding your question about std::move on a const map, the std::move won't do anything in such a case. Since std::move is unconditional cast to rvalue, it'll cast the element to a const reference to an rvalue. Because it's const it'll match the lvalue ctor (copy ctor in this case), and not the move (copy) ctor.
Eg:
const std::string s1 = "Test";
const std::string s2 = std::move(s1);
This will invoke the copy constructor of std::string, not the move constructor. Hence, it'll do a copy, not a move.
This will do a move:
std::string s1 = "Test";
const std::string s2 = std::move(s1);
The s2 parameter in both examples does not have to be const. It makes no difference regarding the copy/move.
There is a 'pythonic' alternative, which you may like if you come from Python, using lambda and a "mapped-reduce" function
std::vector<double> merged = std::accumulate(selected.begin(),
selected.end(),
std::vector<double>(),
[](const std::vector<double>& a, std::vector<double>& b)
{
std::vector<double> result(a);
std::copy(b.begin(), b.end(), std::back_inserter(result));
return result;
});
);
std::move does not actually move data. It casts a reference to a r-value reference, which, if non-const, is a "movable" data type that move constructors can use. But it will never remove a const type qualifier, so using std::move on a const reference will not cast it to a movable type.
int main()
{
int rx = 0;
int ry = std::move(rx); //here is the point of my question
int lx = 0;
int ly = &lx; //(2) obviously doesn't compile
std::cin.ignore();
}
I'm a little bit lost with this aspect of rvalue, I can't understand how we can't bind &&rx to ry, because std::move(rx) is a reference to a rvalue, so I believed that this kind of expression could only be bind to a reference type as is it he case for lvalue reference and illustrated in (2)
References != address-of operator.
int& ly = lx; // reference
int* ly = &lx; // pointer
std::move obtains an rvalue reference to its argument and converts it to an xvalue. [1]
Which in turn can be copied to ry.
The expression int ry = std::move(rx); does not "bind" rx to ry. It tells the compiler that rx is no longer needed and that its contents can be moved to ry while at the same time invalidating rx.
This is especially useful when functions return by value:
std::vector<int> foo() {
std::vector<int> v = {1,2,3,4};
return v;
}
std::vector<int> u = foo();
At return v the compiler notice that v is no longer needed an that it can actually use it directly as u without doing a deep copy of the vector contents.
What would be a declaration likechar *song;
What does the * does? Is it an array, a pointer or something else?
The * (Asterisk) indicates the variable is a pointer. As for a small example:
int x = 0;
int *y = &x; //y is pointing to x
const char* myText = "Text";
You might however be interested in learning a bit more about what pointers are.
H2CO3 is right, you should read up on c, and pointers.
char *song = "smb:d=4,o=5,b=......."
Is the does the same thing as the code below
char song[] = "smb:d=4,o=5,b=......."
In both cases song is a pointer to an array of strings. C++ has a string object, but plain C used c_strings. A c_string is simply a char array. You have what looks like a c_string.
*song //the same as "song[0]" will equal 's'
*(song+1) //the same as "song[1]" will equal 'm'
*(song+2) //the same as "song[2]" will equal 'b'
and so on