compiler says invalid initialization at line 3
I guess creating reference to i, it is telling the compiler that someone wants to change i, I guess this thing came with newer versions of the compilers because i have found this code in most of the books.
int main(){
const int &i=10;
int &j=1;
cout<<j;
return 0;
}
This:
int &j=1;
Is not valid, because you're creating a non-const reference (which would allow you to modify the referent) from a constant value (which cannot be modified, for obvious reasons).
Do this instead:
const int &j=1;
Also, the line that declares i makes no sense. Just delete it.
Besides missing an int in const &i=10; the issue with the next line is that you are creating a reference that is not const (i.e. which allows what it refers to to be changed) and the number 1 is a constant. You'd encounter the same problem with the following code:
const int i = 1;
int &ri = i;
It should be obvious why.
Related
I don't know if it's because I don't need it int the header of the function, but when I do int ticketClass, and int ticketAmount, and put them in the array, it says that the array must have a constant value, when to me at least it seems to already have one, I'm new to arrays and don't know what I did wrong, I appreciate any help I can get.
void customerData(int const CUSTOMERINFO[])
{
int const CUSTOMERINFO = 2;
int ticketClass[CUSTOMERINFO];
int ticketAmount[CUSTOMERINFO];
string moreTickets;
string customerChoice;
int i = 0;
That's not the error. The error is that you're declaring a new variable with the same name as the argument. See here
To fix this, choose a different name. From context here, perhaps CUSTOMER_COUNT or CUSTOMER_LIMIT.
Q1:
I have recently read book C++ Primer, when I read follow:
To substitute the value for the variable, the compiler has to see the variable’s initializer. When we split a program into multiple files, every file that uses the const must have access to its initializer. In order to see the initializer, the variable must be defined in every file that wants to use the variable’s value.
I have a question: when I use a variable defined in other file, I just use extern to declare is enough, why should I must have access to its initializer, so I have done a test:
in main.cpp, I write below:
#include <iostream>
using namespace std;
extern int test;
int main()
{
cout << test << endl;
return 0;
}
in test.cpp, I write below:
int test = 100;
and by the way, these two files are added in the same projects, or it will not build successful.
When I run them, it print
100
like I expect. But in main.cpp, I don't need to define something like int test = 100 like book said. I don't know who is right.
Q2:
int i = 43;
const int &r = i;
i = 1; //when i changed, r alse changed
I have tested in gcc 4.7 and visual studio 2013, they both get same result,
r changed. Then, what's the point of const? Shouldn't r always be 43?
I think the quote from the book means something like the following
const size_t N = 10;
int main()
{
int a[N];
//...
}
If the constant N is defined in some other module with specifier extern then in the module with main the compiler does not have an access to the value of the constant and as result it is unable to define the array
extern const size_t N;
int main()
{
int a[N]; // error: the value N is unknown
//...
}
By this reason constants have internal linkage that it could be possible to define them in each module where their values are required at compile time.
As for the second question then constant references are used that to prevent modifying the referenced objects using references.
For example if you want that some function would not change your compound object you can declare its parameter as a constant reference to the object.
Also a temporary objects are bound to constant references.
Consider an example
void display_string( const std::string &s )
{
std::cout << s << std::endl;
}
you may call the function using a character array. For example
display_string( "Hello, World" );
The compiler implicitly converts the string literal to a temporary object of type std::string and binds it to the constant reference of the parameter.
If the parameter would not be declared like constant reference as for example
void display_string( std::string &s );
then the compiler would issue an error.
Using a constant reference it is supposed that the client code will not change the referenced object itself.
That is the client code may look at the object but may not touch it by hands.:)
Q1. have access to its initializer means compiler need to known the variable's initializer(definition). You can let compiler achieve that by link main.cpp and test.cpp together. You said that these two files are added in the same projects, so IDE will do that for you.
You can find more on this question.
Q2. Compiler don't allow you to change r's value, because it's a reference to a const variable, but i is an integer variable, so you can change it's value.
This question already has answers here:
Modifying a const int in C++ [duplicate]
(2 answers)
Closed 7 years ago.
I have this piece of code:
#include <iostream>
using namespace std;
class X {
public:
const int x;
X(int i) : x(i) { }
int getX() const { return x; }
};
int main()
{
const X d(45);
const_cast<X *>(&d)->x = 47;
cout << d.getX() << endl;
const int j = 3; // j is declared const
int* pj = const_cast<int*>(&j);
*pj = 4;
cout << *pj << endl; //should not work, like above
return 0;
}
As I found here, Even though const_cast may remove constness or volatility from any pointer or reference, using the resulting pointer or reference to write to an object that was declared const or to access an object that was declared volatile invokes undefined behavior. They even proceed to provide examples below, the second one I gave, stating that it should give undefined behavior.
However, on compiling the code and running (here), the second one gives no error, and prints out 4 consistently. Whereas the first one throws error:
assignment of read-only member 'X::x'
const_cast<X *>(&d)->x = 47;
Of course, removing the const from declaration of x in X makes it work fine. However, it is also of the same type of mischief as the first one, changing a const thing through pointer after casting it const_ptr<>. But the first one works while the second one doesn't. Why so?
Both demands undefined behavior which unfortunately could mean working sometimes.
int* pj = const_cast<int*>(&j);
*pj = 4;
Also, Not all compilers are smart enough to figure out this kind of indirect manipulation.
Const-casting anything other than an actual const ptr* is probably a terrible idea, even if it does actually work most of the time.
That being said, the reason why your code doesn't compile properly is pretty straightforward: you remove the constness of the X object, but you fail to also remove the constness of the x member you're trying to modify.
Try this:
*const_cast<int*>(&(const_cast<X*>(&d)->x)) = 47;
I have the following functions (wrote in Visual C++ 2005)
int &getInt_1()
{
int a = 5;
int &p = a;
int p1 = p; // Line 1
return p1;
}
int &getInt_2()
{
int a = 5;
int &p = a;
return p;
}
As I have known so far, both the above functions return address of local variable. If I am right, then I have some questions as follows:
What are the differences between above functions? Why getInt_1() gets warning from the compiler ("returning address of local variable") while getInt_2() does not?
What does Line 1 mean? After Line 1, does p1 become a reference to a as well?
getInt_1 returns a reference to p1. getInt_2 returns a reference to a. Both are the same undefined behavior, don't do it. VC should give a warning on both.
No, you just copy the value.
1) Both are undefined behavior, because of what you pointed out. It's probably an oversight in MSVS.
2) No, p1 does not become a reference itself. That line is equivalent to int p1 = a;
In the first case, it's easy for the compiler to show that you're returning a reference to a local variable; in the second case it's harder, because it just has an arbitrary reference that happens to refer to a local variable. That's probably why you get the warning in the first case but not the second.
And no, in the first case p1 is just a normal int, not an int&.
I am doing a procedure and it's working but I'm not sure if it'll work in all cases as it's not conventional.
void func (int &num){
num=blah;
}
int main() {
int num;
func(num);
}
I know the conventional way of doing this is as below but still I have a lot of code in the previous format I prefer not to change as it works just fine. What I don't understand is whether I'm just being lucky.
void func (int* num){
*num=blah;
}
int main() {
int num;
func(&num);
}
In fact there is a bit more complicated version of it as well:
void func(float* &list){
list=new float[3];
}
int main() {
float *list;
func(list);
}
which again I understand the conventional way of doing it is as below.
void func(float** list){
*list=new float[3];
}
int main(){
float *list;
func(&list);
}
Your help is much appreciated as I'm in total confusion.
Your first example is correct - you're passing an int by reference to func().
Your second example also fine (now that you've edited it). In this case, you're passing an int * by value to func().
Your third and fourth examples are also both correct. In the third, you're passing a float * by reference. In the second case, you're passing a float ** by value (which is semantically similar to passing a float * by reference, which might be why you're confusing them).
There's nothing "conventional" or "unconventional" about any of your example code. All of it is 100% correct and will work fine. Though there are some subtle semantic differences between passing pointers by value and passing by references, these examples are ok.
The syntax with int & is not C, but C++. It is a so-called reference. If your C (not C++) compiler accepts is, then it is a non-standard extension (for a C++ compiler it's part of the language, of course).
The basic mechanics of a reference is that it acts as a name (or another name) for an existing object. For example:
int a;
int& b = a;
b = 3; /* equivalent to a = 3 */
One way to think about the reference is as an automatically dereferenced pointer (that's also how it is commonly implemented). That is, the above code is equivalent to
int a;
int* pb = &a;
*pb = 3;
The Form Func(int &x) is the c++ form of pass by reference c does not support this. It is logically equivocation of passing by a pointer. The comnplier take the address for you implicitly in the call.
In C you would allways declare
Func(int *x)
{ ... }
And call it
Func(&SomeInt);