Difference between `int* const& x` and `int* const x` in C++ - c++

I've read of the differences between passing by value, passing by reference, and passing (a pointer) by constant reference, yet I'm don't understand the difference between the latter, and just passing a constant pointer. As an example, what is the difference between
int PI = 3;
int* getArg(int* const& x){
x = Π
return x;
}
int main() {
}
and
int PI = 3;
int* getArg(int* const x){
x = Π
return x;
}
int main() {
}
Both of these cause the same error: assignment of read-only parameter 'x'.

If you're clear on passing variables by value and by reference, then try breaking down complex types into parts to help make sense of what's going on:
using PointerToInt = int*;
using ConstPointerToInt = PointerToInt const;
int* getArg_v1(ConstPointerToInt x) {
x = Π // it's const by value so you're not allowed to change it
return x;
}
int* getArg_v2(ConstPointerToInt& x) {
x = Π // it's const by reference so you're not allowed to change it
return x;
}

Related

Why cant I post-increment a function call c++

Lets say I have this array and function
int a[] = {1,2};
const int * bar() {
return a;
}
Then in main
int main() {
const int * p1 = bar()++;
}
Why does this throw a compiler error? In my thinking it would return a const int pointer to a and then the post increment operator would move the pointer over to the second element in a.
test.cpp:14:25: error: lvalue required as increment operand
14 | const int * p1 = bar()++;

Reference to pointer and malloc

Consider
int *p;
auto & pp = p;
pp = (decltype(pp))malloc(sizeof(decltype(*pp))); //line1
pp = (decltype(p))malloc(sizeof(decltype(*p))); //line2
why line1 is not acceptible but line2 is fine suggesting they are of different types.
Why pp and p are not of same type?
pp is a reference to an int *
According to https://msdn.microsoft.com/en-us/library/dd293667.aspx
"The following code fragment initializes variable x to type int, variable y to a reference to type const int, and variable fp to a pointer to a function that returns type int."
C++
int f(int x) { return x; }
int main()
{
auto x = f(0);
const auto & y = f(1);
int (*p)(int x);
p = f;
auto fp = p;
//...
}

C++ Return a local or temp variable

Hi guys some problem here:
here is my overloaded operator :
const double & Waz::operator()(int i,int j) const
{
return ((WazImpl const)(*p))(i,j);
}
Where in Waz class I have : WazImpl* p; and in the class WazImpl I have an operator ()
The warning is :
Warning C4172 returning address of local variable or temporary
As far as I understand I'm returning a temp variable which is destroyed somewhere else what can I do to fix it?
Thanks!
If you dissect the function you can see that it is equivalent to the following:
const double& Waz::operator()(int i, int j) const {
// Cast pointer to callable.
const WazImpl& wi = static_cast<const WazImpl>(*p);
// Get result of calling callable.
double d = wi(i, j);
// Return REFERENCE to local object.
return d;
} // All local objects is destroyed and references to them become dangling.
So, you indeed get a dangling reference when calling your Waz::operator.
One solution is to return by value which will return a copy of the result. Also don't return by const value as it makes little sense.
double Waz::operator()(int i, int j) const;
You have two possibilities. The first one is to return simply double instead of the reference const double &
double Waz::operator()(int i,int j) const
{
return ((WazImpl const)(*p))(i,j);
}
The second one is to return the reference to the original value provided that the called operator also returns const reference to double
const double & Waz::operator()(int i,int j) const
{
const double &rd = (WazImpl const)(*p))(i,j );
return rd;
}
Here is a simple example that demonstrates the second approach
#include <iostream>
struct A
{
int & operator ()(){ return a; }
int a = 10;
};
struct B : A
{
int & operator ()()
{
int &ri = A::operator ()();
return ri;
}
};
int main()
{
B b;
b() = 20;
std::cout << b.a << std::endl;
return 0;
}
You should show us the implementation of WazImpl but it seems that WazImpl::operator() const returns a double.
It means that ((WazImpl const)(*p))(i,j) returns a temporary (it exists only in the scope of Waz::operator()).
As Waz::operator() returns a double &, you are indeed returning a reference to a temporary.
Either you are returning a temporary value that just got computed in WazImpl::operator() then you should return a double in Waz::operator() either you are really returning a reference to an existing double in WazImpl and you should fix the signature of WazImpl::operator() const so that it returns a const double&.

"const access error" on sun os when compiling c++ code

Here is my code :
class X
{
public:
X():_x(5){}
void GetVal(int & oVal)
{
oVal = _x;
}
private:
int _x;
};
class Y
{
public:
X * const GetX()
{
return &_x;
}
private:
X _x;
};
int main()
{
Y y;
X * p = y.GetX();
int * pInt = new int[2];
p->GetVal(pInt[0]);
}
In the last line of main, I get an error
Incorrect access of a member from const-qualified function
This error is observed only when the code is compiled on a sun solaris system and doesn't happen on windows or aix system. Any idea why?
Also the strangest thing is that the error is gone if I replace pInt[0], with a simple integer (int a = 0; p->GetVal(a))
The const in X * const GetX() will be ignored, because the result of the function call is an rvalue and rvalues of non class type cannot be const according to c++ const member function that returns a const pointer.. But what type of const is the returned pointer?.
Are you sure you didn't mean to write:
const X * GetX() const
{
return &_x;
}
that is, you change it from returning a constant pointer to variable date into a variable pointer to constant data, and you declare GetX() to be a constant member function, that is a member function that can be used on constant instances of Y: const Y y;
Furthermore in class X, you can change GetVal() to
void GetVal(int & oVal) const
{
oVal = _x;
}

passing const pointer by reference

I am confused that why following code is not able to compile
int foo(const float* &a) {
return 0;
}
int main() {
float* a;
foo(a);
return 0;
}
Compiler give error as:
error: invalid initialization of reference of type 'const float*&' from expression of type 'float*'
but when I try to pass without by reference in foo, it is compiling fine.
I think it should show same behavior whether I pass by reference or not.
Thanks,
Because it isn't type-safe. Consider:
const float f = 2.0;
int foo(const float* &a) {
a = &f;
return 0;
}
int main() {
float* a;
foo(a);
*a = 7.0;
return 0;
}
Any non-const reference or pointer must necessarily be invariant in the pointed-to type, because a non-const pointer or reference supports reading (a covariant operation) and also writing (a contravariant operation).
const must be added from the greatest indirection level first. This would work:
int foo(float* const &a) {
return 0;
}
int main() {
float* a;
foo(a);
return 0;
}