Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Returning an std::pair<std::shared_ptr<A>, std::unique_ptr<B>&> from a function results in weirdness

I’m having trouble understanding the (to me intricate) mechanisms executed behind the scenes in the following code example:

#include <utility>
#include <memory>
#include <iostream>

struct A {int a;};
struct B {int b;};

std::pair<std::shared_ptr<A>, std::unique_ptr<B>&> FuncA() {
    std::shared_ptr<A> a = std::make_shared<A>();
    std::unique_ptr<B> b = std::make_unique<B>();

    a->a = 12; b->b = 13;

    std::cout << "FuncA a: " << a.get() << std::endl;
    std::cout << "FuncA b: " << b.get() << std::endl;

    std::cout << "FuncA a.a: " << a->a << std::endl;
    std::cout << "FuncA b.b: " << b->b << std::endl;

    return {a,b};
}

void FuncC(std::pair<std::shared_ptr<A>, std::unique_ptr<B>&> input) {
  std::cout << "FuncC a: " << input.first.get()  << std::endl;
  std::cout << "FuncC b: " << input.second.get() << std::endl;

  std::cout << "FuncC a.a: " << input.first->a  << std::endl;
  std::cout << "FuncC b.b: " << input.second->b << std::endl;
}

void FuncB() {
  auto ret = FuncA();
  
  std::cout << "FuncB a: " << ret.first.get()  << std::endl;
  std::cout << "FuncB b: " << ret.second.get() << std::endl;

  std::cout << "FuncC a.a: " << ret.first->a  << std::endl;
  std::cout << "FuncC b.b: " << ret.second->b << std::endl;

  FuncC(ret);
}

int main(){
  FuncB();
}

I’ve compiled the code with both GCC and Clang which give similar results:

FuncA a: 0xfeaec0
FuncA b: 0xfeaed0
FuncA a.a: 12
FuncA b.b: 13
FuncB a: 0xfeaec0
FuncB b: 0x7ffd1c8e4a00
FuncC a.a: 12
FuncC b.b: 479087264
FuncC a: 0xfeaec0
FuncC b: 0x406100
FuncC a.a: 12
FuncC b.b: 1449378512

As is clearly visible, the address of the std::unique_pointer reference (and of course also its value) are not the same as within FuncA, but the address and value of the std::shared_pointer are unchanged.

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

What’s happening here, and what (if anything) could be done to make the reference-passing correct?

Is some form of copy-constructor being executed on the std::unique_ptr as a result of returning from FuncA?

>Solution :

std::pair<std::shared_ptr<A>, std::unique_ptr<B>&> FuncA() {
    // ...
    std::unique_ptr<B> b = std::make_unique<B>();
    // ...
    return {a,b};
}

A local std::unique_ptr<B> is created and a reference to it is returned as the second element in the pair. This is a dangling reference and is later accessed, giving the program undefined behaviour.

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading