1

Like I encountered this doubt while learning dynamic memory allocation in C++, and just can't focus anymore on learning it now. :(

    int n;
    cout << "Enter array size: ";
    cin >> n;
    int *p = new int[n];

So everything is fine till now, I just allocated n blocks of int memory in heap area

Now, while taking the input using a for loop, I had this doubt while I tried to write p[i] as *(p+i)

 for (int i = 0; i < n; i++)
    {
        // cin >> p[i];   // This is correct
        // cin >> *(p+i); // This is correct

        cin >> (p + i); // same as cin >> &p[i], right? Now, this gives me error since I didn't deference 
                        // it and now I'm confused as to why we need to deference it? *(p+i) tells which 
                        // block the value is to be stored in, but doesn't (p+i) also give us the same  
                        // address? The input value should still have been stored in the respective memory                                 
                        // block, right? But it doesn't and I can't visualize it why?

        // Also, now I'm even confused as to why writing cin >> n works and writing cin >> &n doesn't??
    }

I was simply expecting that my value should still be accepted into the respective array element, but it didn't, rather it gave me a very very wrong error, which I'm unable to understand.

I tried looking for answers, but still unclear with the concept visualization and clarity. All I've known so far is that cin is an object of istream class, >> operator while used with cin is kind of like a function call, and the variable name which we write after the >> operator is "passed by reference" or something like that, which might seem like that is why maybe we don't give address as reference variable already has it by default, but I'm not sure and still in doubt.

Please someone explain it in proper sequence and with proper example. I'll be grateful.

phuclv
  • 37,963
  • 15
  • 156
  • 475
Deepak
  • 11
  • 6
  • You can simply do `cin >> p[i]`. – kiner_shah Feb 16 '23 at 07:37
  • @kiner_shah: as OP already wrote – Thomas Weller Feb 16 '23 at 07:50
  • you should include the error message in the quesiton. Reading and understanding error messages is an essential skill, we can help you with that – 463035818_is_not_an_ai Feb 16 '23 at 08:44
  • @463035818_is_not_a_number dynamic_memory_allocation.cpp: In function 'int main()': dynamic_memory_allocation.cpp:24:13: error: no match for 'operator>>' (operand types are 'std::istream {aka std::basic_istream}' and 'int*') cin >> (p + i); // same as cin >> &p[i] ~~~~^~~~~~~~~~ In file included from c:\mingw\lib\gcc\mingw32\6.3.0\include\c++\iostream:40:0, from dynamic_memory_allocation.cpp:1: The error goes something like this and after this it is way to big to be posted. So, please could you try out my source code in your compiler and see once. – Deepak Feb 16 '23 at 11:21
  • when i try your code in a compiler I get different errors https://godbolt.org/z/Mfavvxdrs. I had to guess what to add and even if I do this I might get a different error. Thats why it is better if you include a [mcve] and the error message in the quesiton. Though, nevermind, you got answers already, so better not change this question too much – 463035818_is_not_an_ai Feb 16 '23 at 11:23
  • 1
    @kiner_shah I know, but simply moving on with that won't help me right now, I want to know now why this works and &p[i] doesn't. I wan't to deep dive into data buffers, memory management and stuff, they are too fascinating for me. – Deepak Feb 16 '23 at 11:23
  • @463035818_is_not_a_number https://godbolt.org/z/575dhedfc you didn't put the header files, the main function, the declarations so you're not actually getting the error I'm talking about, I've done the same for you, now you may view my error through given link and thank you for letting me know about this compiler explorer where we can actually share our codes and errors through links. – Deepak Feb 16 '23 at 11:38
  • what I said. You do not have to remove the main and the includes before posting the code here. Its explained here: [mcve] – 463035818_is_not_an_ai Feb 16 '23 at 11:43
  • @463035818_is_not_a_number oh got it, on that article now, but you said in your previous comment that I got answers but that still hasn't explained me well enough to make me understand with my problem, so I'm still looking for that particular answer. Also, I would like your suggestion on what topics should I study to understand this? Like is operator overloading, and what else topics? In the second answer provided, there is something called signature of the stream extractor but I have no clue about it, so please help me out. Suggestions are welcome in this comment – Deepak Feb 16 '23 at 11:59
  • imho the question is just too broad and not focused enough, the posted code is incomeplete and one has to guess what the error you refer to is exactly. I would suggest to leave this quesiton be, perhaps decide for one answer to accept, and for the next question try to foucs on 1 specifc question. Sometimes you have a lot of questions but then it is still better to pick only one for one posted question. Note however, that questions on stackoverflow cannot substitute courses or [books](https://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list). – 463035818_is_not_an_ai Feb 16 '23 at 12:02

2 Answers2

2

Type of *(p + i) is int and type of (p + i) is int*. With the first one you are reading an integer, so that is clear.

Why doesn't cin >> (p + i) read int? When a function takes parameter by reference, the parameter must be the same exact type. You are giving it int*, so it will try to read int*.

How would we read a pointer? I guess we could read an integer and assign it to the pointer variable. We are currently reading to the temporary value p + i. operator>> needs a reference, which it cannot get for a temporary value, which is why you get a compile error.

Let us skip this problem by using another variable:

int* pi = p + i;
cin >> pi;

This still does not compile, because there is an overload for reading void*, but not int*. In C++, you cannot automatically convert between two pointer types. If you want to read int*, you can do that, but you have to write an overload for operator>>.

VLL
  • 9,634
  • 1
  • 29
  • 54
  • 1
    BTW: Letting the user input an address is not a good idea. Chances that this address is invalid is quite high. It will very likely result in UB. I also don't think that this is what OP wanted. Maybe you should have left it out of the answer. – Thomas Weller Feb 16 '23 at 07:49
  • The type of `*(p + i)` is `int&`, not `int`. +1. – Pete Becker Feb 16 '23 at 13:57
0

the variable name which we write after the >> operator is "passed by reference"

This is exactly the point. One of the main goals of the C language was to build a rather simple compiler able to provide efficient code. As a result, it tried to remain as explicit as possible and only allowed to pass parameters to functions as values. If you want to modify something from a function you just pass a pointer to it.

C++ language is aimed at a much higher level. Proper pointer handling is not always trivial and memory allocation is not either. The philosophia of C++ is that those are gory details that should be hidden to a high level program. For that reason, many SO users advise to never use new[] and delete[] (explicit allocation) but rely on containers which correctly handle the subtilities of automatic deallocation, and copy and move semantics.

For the same reason, references were introduced in the language. At first sight, they just look like disguised pointers to old C programmers, meaning useless syntactic suger, and worse contradictory with the C idiom requiring a pointer to modify a variable from a function (what operator << indeed is at a lower level). But that is exactly what they are for: you can act directly on the variable without explicitly dereferencing it, which removes the risk of forgetting a * somewhere in the code.

And actually, the signature of the stream extractor is:

istream& operator << (istream& in, int& val);

So the function is able to modify the stream itself and the passed variable.

Serge Ballesta
  • 143,923
  • 11
  • 122
  • 252