在C++中传递引用选项

8
我希望能够通过引用(广义上的引用,即A&或A*)将A类对象(称为a)传递给另一个B类的构造函数。我不希望在B内修改'a'('a'是只读的且大小较大,这就是我想要通过引用传递它的原因)。我知道两个选项:
1)将'a'作为参数传递,并将其声明为const引用
2)将'a'作为指针传递,并将其声明为const指针
const A & a_

2) 将'a'作为参数传递

const A * a_

选项1的缺点是我可能会错误地传递r值。选项2的缺点是我可能会错误地传递空指针。
我的问题是: 1)我对上述缺点正确吗? 2)是否有其他推荐的通过引用传递'a'的方法?
我在下面的链接中看到了答案。但我很好奇除了那个问题中发布的内容之外,是否还有其他选项。 在C++中通过指针传递而不是通过引用传递有什么好处?

5
你错误地传递一个 r-value 的概率有多大,这种行为的后果有多严重? - emlai
1
如果你有疑虑并且知道问题所在,你需要进行错误检查。通过引用传递并使用try/catch。如果你使用指针,你将修改对象的原始实例。 - David Pulse
1
什么是rvalue?它是否是未定义的相等性?像lvalue一样吗? - David Pulse
1
@DavidPulse http://en.cppreference.com/w/cpp/language/value_category@DavidPulse http://en.cppreference.com/w/cpp/language/value_category - emlai
1
@DavidPulse: 他可能是在之前的评论中指的是 const_cast<A*>。Riju: C++为程序员提供了安全防护,但几乎每种安全措施都有后门,以备不时之需。没有100%的保护,但 const A* 对于你正在做的事情来说已经足够安全了。 - Mooing Duck
显示剩余2条评论
3个回答

18

通过 const A & 传递参数。

您可以声明一个函数的右值引用重载 = delete,以防止意外传递 rvalue。例如:

struct A { };

void func(const A & a) { }
void func(A && a) = delete;

int main()
{
    A a;
    func(a);   // compiles
    func(A()); // doesn't compile
}

1
在处理这个问题时,我遇到了一个棘手的问题:如果你真的想禁用所有 rvalue,最好使用void func(const A&&) = delete;。看起来很奇怪和肮脏,但它确实完成了工作。这是因为否则返回const值的旧代码(不建议,但不幸的是在类似工厂的函数中经常使用)将绑定到func(const &);。相关链接:http://stackoverflow.com/q/33244951/3093378 - vsoftco

4
请看std::reference_wrapper的构造函数:http://en.cppreference.com/w/cpp/utility/functional/reference_wrapper/reference_wrapper 它有一个额外的被删除的构造函数,接受右值引用,因此如果您尝试将右值传递给它,那么这个构造函数会赢得重载解析并导致错误。
您也可以做同样的事情:声明const A&A&&两个构造函数,并删除后者。然后没有人能够传递一个右值。

-3

代码:

#include <iostream>
using namespace std;

struct A
{ };

int func_one(A& var) {
    A * insertVal=new A;
    if (&var==nullptr)
        return 0;
    else
        return 1;
}

int main() {
    A refVar;
    int x;
    x=func_one(refVar);

    return 1;
}

2
这个无法编译。 - emlai
2
尝试编译它,查看您得到了哪些错误,并首先修复那些错误。只有无效代码的仅包含代码的答案并不是非常有用。 - emlai
1
func_one在所有控制路径上都没有返回值并且存在内存泄漏。如果new无法分配内存,它不会返回nullptr - Neil Kirk
感谢@Neilkirk,你比所有人都更了解我不太适合这些更偏向于编码的人的视角。我只是在尽我最大的努力。 - David Pulse
@neilkirk 再次感谢,我不太擅长 C++ 但感谢您没有给我点踩。 - David Pulse

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接