C++ 在编码约定中使用boost::ref表示意图

C++ 在编码约定中使用boost::ref表示意图,c++,boost,coding-style,conventions,ref,C++,Boost,Coding Style,Conventions,Ref,当函数将非常量引用作为参数时,它可能会创建难以读取的代码,因为在调用站点,不清楚哪些输入可能会被更改。例如,这导致一些代码约定强制使用指针 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)

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

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

void func(int input, int& output);

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

这将被用作公司编码惯例我的问题是,这不是一个好主意,有什么原因吗?

这家公司的编码惯例很容易(当然是错误地)被这样打破:

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这样的错误是不可能的

这不是一个坏主意,但并没有真正强制执行(正如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);
}
模板
类输出参数
{
公众:
模板
友元输出参数输出(U&ref);
T&get()常量
{
返回mRef;
}
算子T&()常数
{
返回get();
}
私人:
显式输出参数(T&ref):
mRef(参考)
{}
输出参数&运算符=(常量输出参数&);//未定义
T&mRef;
};
模板
输出参数输出(U&ref)
{
返回输出参数(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));
}
void foo(int x,输出参数f)
{
int i=静态(f);
f、 get()=static_cast(i+x);
}
int main()
{
浮球f=5.0f;
//失败:foo(1,f);
foo(1,out(f);;
}

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

此外,使用移动语义,您在返回值时不必为副本支付性能惩罚。因此,使用out参数的典型模式应该很少见。我不太喜欢避免非常量引用,因为您需要查看函数的声明,以确保调用正确(正确的参数数量,正确的类型)。我不认为您的想法是一个坏主意的任何原因,我只是觉得从长远来看,这对你没什么好处。