-1

I have the following code snipet:

// code snipet one:
#include <memory> 
#include <iostream> 
#include <queue>

struct A {
    uint32_t val0 = 0xff;

    ~A() {
        std::cout << "item gets freed" << std::endl;
    }
};

typedef std::shared_ptr<A> A_PTR;

int main() 
{ 
    std::queue<A_PTR> Q;
    Q.push(std::make_shared<A>());
    auto && temp_PTR = Q.front();
    std::cout << "first use count = " << temp_PTR.use_count() << std::endl;
    Q.pop();
    std::cout << "second use count = " << temp_PTR.use_count() <<std::endl;
    return 0;
}

After running it, I got the result as following:

first use count = 1                                                                                                                         
item gets freed 
second use count = 0

Q1: is anybody can explain what the type of temp_PTR after the third line of main function is called?

if I change that line as

A_PTR && temp_PTR = Q.front();

compiler complains that

main.cpp: In function 'int main()':
main.cpp:26:32: error: cannot bind '__gnu_cxx::__alloc_traits > >::value_type {aka std::shared_ptr}' lvalue to 'A_PTR&& {aka std::shared_ptr&&}'
     A_PTR && temp_PTR = Q.front();

Q2: I remember that the return value of a function should be a r-value, but it seems here the compiler tell me: " hey, the return value of Queue.front() is a l-value", why is here?

Dongwei Wang
  • 475
  • 5
  • 14
  • "because it is a performance loss" - Is that claim of yours backed up by any measurements? – SirGuy Feb 06 '18 at 20:03
  • As for your second question, there is no one type that a function should return, sometimes you want to return by value, sometimes you want to return by const reference, sometimes by non-const reference. Look up the documentation for functions that you are unsure of on a site like [this one](http://en.cppreference.com/w/) to find out what it does in detail. – SirGuy Feb 06 '18 at 20:07
  • "I think the following code should work", what happened when you tried it? – SirGuy Feb 06 '18 at 20:07
  • It works, and print the number of shared_ptr correctly, and the cout info of destructor is at the end of the program – Dongwei Wang Feb 06 '18 at 20:10
  • So why do you need another solution? Are you concerned that the `std::move` solution will be too slow? If that's the case I recommend you measure it and see how long it takes, but I almost guarantee that if your program is slow it's not because you copied vs. moved your `shared_ptr` around. – SirGuy Feb 06 '18 at 20:12
  • I apologise if my tone in these comments seems harsh, but I do feel that your question is very misguided right from the start and my advice is to not worry about the performance until it is demonstrably a problem. Once your program gets to be too slow don't guess what the problem is, measure and prove where it is slow and then work on improving that. – SirGuy Feb 06 '18 at 20:15
  • No, it is okay, you point my confuse and help me to resolve the Q2. For Q3, I just want to know more and understand clearly about the auto l-value, r-value, and move-constructor these kind things, maybe my question confused you, I will update my post. – Dongwei Wang Feb 06 '18 at 20:23
  • The type of `temp_PTR` in `auto && temp_PTR` is `A_PTR &`, look up forwarding references for more information on that. This is different than `A_PTR &&` which is an rvalue reference, which you should be able to look up more information on as well. I recommend that once you read up on those concepts if you are still confused choose one question you have and then ask that in a new question. Avoid asking several questions in one 'question', it is more difficult for us to answer several questions at once. – SirGuy Feb 06 '18 at 21:07
  • Thanks for your explanation of Q1, I will dig more. Since these questions come from the same code, that is why I put them all in one, it is easier to explain the context. – Dongwei Wang Feb 06 '18 at 21:30
  • Actually the key phrase to learn about is "reference collapsing". It existed long before "perfect forwarding". – Ben Voigt Feb 06 '18 at 21:44

1 Answers1

0

For Q2, I just check the C++ docs, that the return value of Queue.front() is refernece, that means it return a l-value

reference& front();
const_reference& front() const;

For Q3, it works for A_PTR temp_PTR = std::move(Q.front());, it is what I want.

Dongwei Wang
  • 475
  • 5
  • 14