是否可以通过引用传递的参数返回引用?

时间:2019-07-31 16:24:50

标签: c++ reference rvalue

我想从该函数返回一个布尔值或成功/失败枚举,并通过引用修改参数。但是,我想在调用函数中构造一个引用,而不是复制该值。

我有一些容器(例如std :: queue类型的“ example_q”)。 queue.front()将返回对存储在队列中的值的引用。我可以复制该引用(示例A),也可以复制该引用(示例B),从而允许该值保留在队列中,但可以在队列外使用。

A)

int a = example_q.front();

B)

int& b = example_q.front();

使用这种差异,我还可以返回排队的值:

A)

int get_front()
{
    int a = example_q.front(); 
    return a;
}

B)

int& get_front()
{
    return example_q.front();
}

使用选项'B'可以避免不必要的复制,而无需通过std :: move()语义将数据移出队列。

我的问题是,我可以通过引用传递的参数来执行“ B”吗?我需要以某种方式使用std :: move()/ rvalues / &&&吗?

void get_front(int& int_ref)
{
    // somehow don't copy the value into referenced int_ref, but construct 
    // a reference in the caller based on an input argument?
    int_ref = example_q.front(); 
}

要解决的问题是使API与其他修改引用参数但返回成功/失败值的函数匹配,即:

if(q.get_front(referrence_magic_here))
{
    ...
}

我可以颠倒顺序以得到所需的结果,即IE:

int& get_front(bool& success)
{
    ...
}

但是我宁愿保留API的模式,并尽可能在if()语句中通过一行完成它。

也许是这样的:

bool get_front(int&& int_rvalue)
{
    ...
    int_rvalue = example_q.front();
    ...
    return true_or_false;
}


void calling_func()
{
    ...
    if(get_front(int& magical_ref))
    {
       ... //use magical_ref here?
    }
    ...
}

3 个答案:

答案 0 :(得分:7)

不,你不能那样做。

除了在初始化程序中,引用的行为与其引用的对象相似。通过将其作为函数参数传递,您可以从要进行分配的部分“隐藏”初始化程序。因此,该函数无法访问事物的引用行为。

如果要执行此操作,则必须使用指针:

void get_front(int*& int_ptr)
{
    int_ptr = &example_q.front(); 
}

int* ptr = nullptr;
get_front(ptr);

// optional:
int& ref = *ptr;

(Ew!)

选项B很好。

答案 1 :(得分:4)

此代码是无效的C ++:

if(get_front(int& magical_ref))

在将新变量传递给函数时,无法声明新变量。并且由于必须同时声明和初始化引用变量,因此不可能通过将引用传递给函数来对其进行初始化。

可以,但是,请执行以下操作:

if(int &magical_ref = get_front()) {

但是请注意,您将要检查magical_ref是否为0,这与示例中的条件不同。

如果您的逻辑与比较int一样简单,则可以执行以下操作:

if (int& magical_ref = get_front(); magical_ref == 42)

答案 2 :(得分:1)

您可以返回std::tuple<int&, /* status condition */>并检查状态。例如:

std::tuple<int&, bool> get_front() {
    static int example = 0;
    return {example, false};
}

...

// C++17's structured bindings + if statement with initializer
if (auto [ref, success] = get_front(); success) {
    ref = 42;
}

Demo