3

当函数将非常量引用作为参数时,它可能会创建难以阅读的代码,因为在调用站点上可能会更改哪些输入并不明显。这导致一些代码约定强制使用指针,例如

void func(int input, int* output);

int input = 1, output = 0;
func(input, &output);

代替

void func(int input, int& output);

int input = 1, output = 0;
func(input, output);

就个人而言,我讨厌使用指针,因为需要检查空值。这让我想知道是否可以使用 boost::ref (或 C++11 的 std::ref )来表示意图,如下所示:

void func(int input, int& output);

int input = 1, output = 0;
func(input, boost::ref(output));

这将用作公司编码约定。我的问题是,有什么理由说明这不是一个好主意吗?

4

2 回答 2

3

这不是一个坏主意,但并没有真正执行(如 PiotrNycz 所述)。它实际上只是一个评论。

我们可以做得更好:

template <typename T>
class output_argument
{
public:
    template <typename U>
    friend output_argument<U> out(U& ref);

    T& get() const
    {
        return mRef;
    }

    operator T&() const
    {
        return get();
    }

private:
    explicit output_argument(T& ref) :
    mRef(ref)
    {}

    output_argument& operator=(const output_argument&); // not defined

    T& mRef;
};

template <typename U>
output_argument<U> out(U& ref)
{
    return output_argument<U>(ref);
}

给予:

void foo(int x, output_argument<float> f)
{
    int i = static_cast<int>(f);

    f.get() = static_cast<float>(i + x);
}

int main()
{
    float f = 5.0f;

    //fails: foo(1, f);
    foo(1, out(f));
}

但通常这些实用程序不是必需的,因为函数名称应该传达参数发生的情况:swap(x, y)非常清楚地修改了参数!并且返回值应该使用返回类型来完成,进一步限制了这个实用程序可以使用的情况。

于 2012-11-01T22:59:23.693 回答
1

这个公司的编码约定很容易(当然是错误地)被打破,如下所示:

void func(int input, int& output);

int input = 1, output = 0;
func(boost::ref(input), output);

这编译和工作正常 - 但会误导读者。

最好让 func 有个好名字,建议在其中修改一些参数:

void copyTo(int input, int& output);

在现代 IDE 中 - 您可以在阅读该函数的功能时看到。


也许更好的公司编码约定会以相反的方式,通过使用 boost::cref:

void func(int input, int& output);

int input = 1, output = 0;
func(boost::cref(input), output);

像 boost::ref 这样的错误是不可能的......

于 2012-11-01T22:47:41.043 回答