c++ - 避免返回引用参数

标签 c++ c++11

假设我有一个类 Option:

template<typename T>
class Option {
public:
    Option() noexcept
    {}

    Option(T val) noexcept : val_(std::make_shared<T>(std::move(val)))
    {}

    const T & get() const
    {
        if (val_ == nullptr) {
            throw std::out_of_range("get on empty Option");
        }
        return *val_;
    }

    const T & getOrElse(const T &x) const
    {
        return val_ == nullptr ? x : *val_;
    }

private:
    std::shared_ptr<T> val_;
};

传递给 Option::getOrElse 的参数是当此 Option 为空时返回的默认值:

Option<int> x;  // empty
int y = 123;
x.getOrElse(y);  // == 123

但是,我认为下面的代码是不安全的:

Option<int> x;
x.getOrElse(123);  // reference to temporary variable!

一种更安全的方法是从 Option::getOrElse 中按值返回,但是当 Option 为非空时,这会很浪费。我能以某种方式解决这个问题吗?

更新:我正在考虑是否重载 getOrElse 的参数类型(左值/右值),但还没有弄清楚具体如何操作。

更新 2:可能是这个?

T getOrElse(T &&x) const { ... }

const T & getOrElse(const T &x) const { ... }

但我认为这可能有歧义,因为左值和右值参数都符合第二个版本。

最佳答案

However, I think the following code is not safe:

Option<int> x;
x.getOrElse(123);  // reference to temporary variable!

你是对的。这就是为什么 std::optional::value_or() 返回 T 而不是 T&T const& .根据 N3672 中的理由:

It has been argued that the function should return by constant reference rather than value, which would avoid copy overhead in certain situations:

void observe(const X& x);

optional<X> ox { /* ... */ };
observe( ox.value_or(X{args}) );    // unnecessary copy

However, the benefit of the function value_or is only visible when the optional object is provided as a temporary (without the name); otherwise, a ternary operator is equally useful:

optional<X> ox { /* ... */ };
observe(ox ? *ok : X{args});            // no copy

Also, returning by reference would be likely to render a dangling reference, in case the optional object is disengaged, because the second argument is typically a temporary:

optional<X> ox {nullopt};
auto&& x = ox.value_or(X{args});
cout << x;                              // x is dangling!

我建议您遵循相同的准则。如果您确实需要避免复制,请使用三元组。这是安全且不可复制的:

Optional<int> ox = ...;
const int& val = ox ? *ox : 123;

如果你真的不这样做,或者 Optional 无论如何都是一个右值,getOrElse() 会更简洁。

关于c++ - 避免返回引用参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36993646/

相关文章:

c++ - 将表从一个 lua 状态传递到另一个

c++ - 制作模板元函数以在编译时创建单位矩阵

C++ 入门 1.4.4。不能完全理解第一个 IF 语句的需要

c++ - Poco C++ 与柯南依赖管理器的链接问题,我该如何解决?

c++ - 从 C++ 中小于给定值 d 的十六进制的所有数字中减去 1

C++ : Segmentation fault (core dumped) issue

c++ - 给出了在 C++ 中返回对象的各种方法,这些 return 语句中的每一个的潜在问题是什么

c++ - Raspberry Pi 优化的 backtrace()

c++ - 多种类型的类模板特化

c++ - 如何在 gmock 中测试失败