C++中如何按值传递引用?
-
19-08-2019 - |
题
我正在尝试在 C++ 中创建不可变类型(类),
我这样做是为了让所有方法“又名成员函数”不会修改对象并返回一个新实例。
我遇到了很多问题,但它们都围绕着 C++ 中的引用类型。
一个例子是通过引用传递相同类类型的参数时:
Imm Imm::someOp( const Imm& p_im ) const
{
...
p_im = p_im.someOtherOp(); //error, p_im is const, can't modify it!
...
}
该错误是由引用传递值引起的。相反,如果我按值传递引用,那么上面的错误行就不会是错误!
考虑一个 Java/C# 示例
class Imm
{
...
Imm someOp( Imm p_im )
{
....
p_im = p_im.someOtherOp(); //ok, you're not modifying the
//original object, just changing the local reference
....
}
....
}
我怎样才能在 C++ 中做这样的事情?我知道我可以使用指针,但后来我遇到了整个内存管理混乱。我不想担心谁拥有对象的引用。
理想情况下,我想将类设计得像 python 中的不可变字符串;您可以使用它们,而无需注意甚至不知道它们是不可变的,并且它们的行为就像您所期望的那样;他们只是工作。
编辑
当然,我可以通过按值传递或使用临时变量(这就是我当前正在做的事情)来解决它。我要问的是“如何在 C++ 中按值传递引用”
我期待答案围绕 STL 中的某些内容,我目前正在研究 smart_ptr 系列模板。
更新
感谢您的回复,我意识到无法逃避指针。(参见我的 其他问题, ,这实际上是这个的后续)
解决方案
在Java和C#中,你并没有真正处理的参考 - 他们更像是句柄或指针。在C ++中的参考文献是真正的原始对象,而不是指向它的指针(尽管它可以用一个指针实现)的另一个名称。当你分配一个值的引用,你是指派对象本身。存在这样的困惑初始化,您可以使用=
字符的参考,但它是一个初始化,不是赋值。
Imm im, im2, im3;
Imm &imr = im; // initialize a reference to im
imr = im2; // assign im2 to imr (changes the value of im as well)
Imm *imp = &im; // initialize a pointer to the address of im
imp = &im3; // assign the address of im3 to imp (im is unnaffected);
(*imp) = im2; // assign im2 to imp (modifies im3 as well).
如果你特别想通过“按值引用”,那么你基本上是要求在用词上矛盾性。引用,顾名思义是通过引用传递。正如其他地方所指出的,你可以通过值传递一个指针,否则直值。如果你真的想,你可以守住一类的引用和周围通过值:
struct ImmRef
{
Imm &Ref;
ImmRef(Imm &ref) : Ref(ref) {}
};
还要注意的是一个const施加到参考正在使称为对象恒定,而不是参考。引用总是常量。
其他提示
时不分配,根据定义,不是一个常数操作?
您看起来像你想分配的东西const引用,这完全违背了一个const引用的想法。
我想你可能会寻找一个指针,而不是参考。
它不会像在C ++工作
当你传递一个参考到对象时,实际上是通过在地址中的对象的存储器。引用不能被重新安置到其他对象或者,因此C ++谚语“基准是对象”。你必须作出一个拷贝进行修改。 Java将做到这一点的场景,在你身后。 C ++,你只需要复制它。
你没忘记设置你打电话为const的方法?
编辑:所以,用const固定
也许你应该这样做。
Imm & tmp = p_im.someOtherOp();
然后执行进一步的操作上TMP变量。
如果您设置一个变量或参数为const&你就不能分配给它。
检查此项以了解临时生命周期 http://herbsutter.wordpress.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
Imm Imm::someOp( const Imm& p_im ) const
{
...
//Imm& im = p_im.someOtherOp(); // will *not* work
const Imm& im = p_im.someOtherOp(); // will work, but you get a const reference
...
}
但你可以使用 boost::shared_ptr
shared_ptr<Imm> Imm::someOtherOp() const
{
shared_ptr<Imm> ret = new Imm;
...
return ret;
}
shared_ptr<Imm> Imm::someOp(const share_ptr<Imm>& p_im) const
{
shared_ptr<Imm> im = p_im->someOtherOp();
}
您需要让你进入论证的新副本。你可以做你想做的事,相当于几个方面:1),你可以通过按值:
Imm Imm::someOp( Imm im ) const {
im = im.someOtherOp(); // local im is a copy, original im not modified
return im; // return by value (another copy)
}
或2),则可以通过按引用并作出明确的副本:
Imm Imm::someOp( const Imm & im ) const {
Imm tmp = im.someOtherOp(); // local tmp is a copy
return tmp; // return by value (another copy)
}
这两种形式是等价的。
C ++有一些比不变类型-const
更好。单个类型可以是可变的,或不依赖于你的需求。这就是说,存在用于处理短寿命(近)拷贝有用的模式:
void f(const X &x) {
// Trivial case: unconditional copy
X x2=transform(x);
// Less trivial: conditional copy
std::optional<X> maybe;
const X &use=need_copy ? maybe.emplace(transform(x)) : x;
use.go(); // whichever, x or *maybe
} // *maybe destroyed iff created, then x2 destroyed
std::unique_ptr
可以以类似的方式之前,C ++ 17被使用,虽然功能可以那么当然掷std::bad_alloc
。