help with reference usage

Write your question here.
Hi, compiler gave me error about the reference line:
vector<int>& c = res.back(); and c = res.back();
I cant figure out why i cant use reference this way.
Thank you folks
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
  vector<vector<int>> merge(vector<vector<int>>& intervals) {
     sort(intervals.begin(), intervals.end(),
     [](const vector<int>& lft, const vector<int>& rgh){
         return lft[0] < rgh[0];
     });
     vector<vector<int>> res;
     res.push_back(intervals[0]);
     vector<int>& c = res.back();
     for (int i = 1; i < intervals.size(); ++i)
     {
         if (res.back()[1] >= intervals[i][0])
         {
             //res.back()[1] = max(res.back()[1], intervals[i][1]);
             c[1] = max(c[1], intervals[i][0]);
         }
         else
         {
             res.push_back(intervals[i]);
             c = res.back();
         }
         
     }
     return res;
}
what does the error message say?

The code as posted compiled and only warned that int vs size() has a sign mismatch. Perhaps you have a call to this function(??) in your code and it finds an error due to trying to compile the call into it?

you have to be careful trying to hold a pointer or reference to an item in a vector because any change in size (cough: push back!) can invalidate the pointer or reference. You may be able to trigger an error due to this, but that isn't shown in your snip. The way around that is simply to use an index instead...

int c = res.size()-1
intervals[c] is what you used to think of as c.

you can use a typedef or using statement to mask redundant complexity (eg if you have 50 lines of code that all refer to intervals[c] you can rename that to 'intback' or something meaningful, hiding the repeated access code. I don't like doing that outside of extreme circumstances where you have more calls to the thing than lines of code, eg if every line accessed it 3-4 times as likes to happen in math problems. So you can 'using' c as intervals[res.size()-1]. And you probably need to test that intervals isn't empty, and if it is, gracefully deal with it.
Last edited on
Thank you for the reply. I'm running it here: (im doing this for interview)https://leetcode.com/problems/merge-intervals/
i don't really understand whats the meaning of the error message:
and the message is like:
Runtime Error
=================================================================
==22==ERROR: AddressSanitizer: heap-use-after-free on address 0x6030000000b0 at pc 0x000000369775 bp 0x7ffff11ca7e0 sp 0x7ffff11ca7d8
READ of size 8 at 0x6030000000b0 thread T0
#3 0x7ffb02b9d082 (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
0x6030000000b0 is located 16 bytes inside of 24-byte region [0x6030000000a0,0x6030000000b8)
freed by thread T0 here:
#4 0x7ffb02b9d082 (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
previously allocated by thread T0 here:
#4 0x7ffb02b9d082 (/lib/x86_64-linux-gnu/libc.so.6+0x24082)
Shadow bytes around the buggy address:
0x0c067fff7fc0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c067fff7fd0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c067fff7fe0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c067fff7ff0: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x0c067fff8000: fa fa 00 00 00 07 fa fa fd fd fd fa fa fa fd fd
=>0x0c067fff8010: fd fa fa fa fd fd[fd]fa fa fa fa fa fa fa fa fa
0x0c067fff8020: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8030: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8040: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8050: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
0x0c067fff8060: fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa fa
Shadow byte legend (one shadow byte represents 8 application bytes):
Addressable: 00
Partially addressable: 01 02 03 04 05 06 07
Heap left redzone: fa
Freed heap region: fd
Stack left redzone: f1
Stack mid redzone: f2
Stack right redzone: f3
Stack after return: f5
Stack use after scope: f8
Global redzone: f9
Global init order: f6
Poisoned by user: f7
Container overflow: fc
Array cookie: ac
Intra object redzone: bb
ASan internal: fe
Left alloca redzone: ca
Right alloca redzone: cb
Shadow gap: cc
==22==ABORTING
It is of course not a compiler but a runtime message.

First you expect that intervals has at least the size [1]2]. A rather dangerous assumption...

Line 19 doesn't work. Line 18 invalidates c and on line 19 you try to assign something to that invalid object which crashes.
A reference cannot be reassigned. What exactly are you trying to do there? My suggestion: get rid of c.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Foo bar;
Foo gaz;
vector<Foo> res;
res.push_back(bar);
// res[0] is copy of bar
vector<int>& c = res.back(); // make c point to res[0]
// c is a reference to res[0]
res.push_back(gaz);
// res[1] is copy of gaz
// res may have reallocated. If so, address of res[0] has changed
// c might refer to invalid memory

c = res.back(); // copy res[1] to wherever c points to
// if c is valid, then same as res[0] = res[1];
// if c is invalid, then access violation 
What you think is a reference to a vector's element is actually the underlying data type, in this case an int. There is no need for fancy code footwork to access the container's elements.

I know what cppreference says, but the returned type is not a C++ reference (&).
https://en.cppreference.com/w/cpp/container/vector/back

(Read the Notes section)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <iostream>
#include <vector>
#include <typeinfo>

int main( )
{
   std::vector<int> v { 1, 2, 3, 4, 5, 6 };

   int n = v.back( );

   std::cout << n << '\t' << v.back( ) << '\n';

   std::cout << typeid(n).name( ) << '\t' << typeid(v.back( )).name( ) << '\n'
             << typeid(v).name()  << '\n';
}

http://coliru.stacked-crooked.com/a/d5e95e80691e13f8
6	6
i	i
St6vectorIiSaIiEE

GCC produces typeid names that are, to be blunt, a bit terse and IMO not very helpful. MSVC++ produces typeid names that are more hoo-man readable:
6       6
int     int
class std::vector<int,class std::allocator<int> >

As coder777 points out there are other problems with your code.
If you really, really want to hold refs/iterators to elements of a vector and insist on using operations that may result in a memory re-allocation, then you need to compare capacity() before and after the operation and if they are different then you need to reset all those refs/iterators as their values are now invalid.
Last edited on
I want to hold the reference because in the thinking of once i change the reference value, vector.back() value is changed. I can directly write to the last position of the vector though.
Thank you all for the answers ! I understand the issue now.
Topic archived. No new replies allowed.