如何在 C++ 中按值传递引用?
我正在尝试在 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 系列模板。
更新
感谢您的回复,我意识到指针是无法逃脱的。 (请参阅我的其他问题,这实际上是这个问题的后续问题)
I'm trying to create am immutable type (class) in C++,
I made it so that all methods "aka member functions" don't modify the object and return a new instance instead.
I'm running across a bunch of issues, but they all revolve around the reference types in C++.
One example is when passing parameters of the same class type by reference:
Imm Imm::someOp( const Imm& p_im ) const
{
...
p_im = p_im.someOtherOp(); //error, p_im is const, can't modify it!
...
}
The error is caused by passing the value by reference.
If instead, I was passing the reference by value, then the error line above would not be an error!
Consider a Java/C# example
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
....
}
....
}
How can I do something like this in C++? I know I can use pointers but then I run into the whole memory management mess. I don't want to worry about who owns references to objects.
Ideally I'd like to design the class to be like immutable strings in python; you can use them without ever noticing or even knowing that they're immutable, and they just behave as you expect; they just work.
EDIT
Of course I can get around it by passing-by-value or by using a temp variable (which is what I'm doing currently). What I'm asking about is "how to pass references by value in C++"
I'm expecting the answer to revolve around something in the STL, I'm currently looking into smart_ptr family of templates.
UPDATE
Thanks for the responses, I realize there's no escape from pointers. (see my other question, which is really a follow up on this one)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
在 Java 和 C# 中,您实际上并不是在处理引用 - 它们更像是句柄或指针。 C++ 中的引用实际上是原始对象的另一个名称,而不是指向它的指针(尽管它可以用指针实现)。 当您将值分配给引用时,您正在分配给对象本身。 令人困惑的是,要初始化引用,您可以使用
=
字符,但它是初始化,而不是赋值。如果您特别想传递“按值引用”,那么您实际上是在寻求术语上的矛盾。 根据定义,引用是通过引用传递的。 正如其他地方所指出的,您可以按值传递指针,也可以直接传递值。 如果您确实愿意,您可以保留类中的引用并按值传递它:
另请注意,应用于引用的 const 使引用的对象成为常量,而不是引用。 引用始终是 const。
In Java and C#, you are not really dealing with a reference - they are more like handles or pointers. A reference in C++ is really another name for the original object, not a pointer to it (although it may be implemented with a pointer). When you assign a value to a reference, you are assigning to the object itself. There is confusion in that to initialize a reference you can use the
=
character, but it is an initialization, not an assignment.If you specifically want to pass "references by value" then you are essentially asking for a contradition in terms. References, by definition are passed by reference. As pointed out elsewhere, you can pass a pointer by value, or else a straight value. If you really want, you can hold onto a reference in a class and pass that around by value:
Note also that a const applied to a reference is making the referred to object constant, not the reference. References are always const.
根据定义,赋值不是一个常量操作吗?
您看起来像是在尝试将某些内容分配给 const 引用,这完全违背了 const 引用的想法。
我认为您可能正在寻找指针而不是引用。
Isn't assignment, by definition, not a constant operation?
You look like you're trying to assign something to a const reference, which totally defeats the idea of a const reference.
I think you may be looking for a pointer instead of a reference.
它不像 C++ 那样工作。
当你传递一个对象的引用时,你实际上传递的是该对象在内存中的地址。 引用也不能重新定位到其他对象,因此 C++ 谚语“引用就是对象”。 您必须复制一份才能修改它。 Java 会在幕后为您完成此操作。 C++,你只需复制它即可。
It doesn't work like that in C++.
When you pass a reference to an object, you are actually passing the address in memory of the object. References can't be re-seated to other objects either, hence the C++ adage "the reference IS the object." You HAVE to make a copy to modify it. Java will do this behind the scenes for you. C++, you just have to copy it.
你没有忘记将你调用的方法设置为const吗?
编辑:所以,const 固定。
也许您应该执行类似“
然后对 tmp 变量进行进一步操作”的操作。
如果将变量或参数设置为 const & 你只是不能分配给它。
Didn't you forget to set the method you call as const?
EDIT: so, with the const fixed.
Maybe you should do something like
Then do further operation on the tmp variable.
If you set a variable or a parameter as const & you just cannot assign to it.
检查此内容以了解临时生命周期 http://herbsutter.wordpress.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
但是你可以使用 boost::shared_ptr
Check this to know about temporary lifetime http://herbsutter.wordpress.com/2008/01/01/gotw-88-a-candidate-for-the-most-important-const/
But you can use boost::shared_ptr
您需要为传入的参数制作一个新副本。 您可以通过几种等效的方式执行您想要的操作:1)您可以按值传递:
或2)您可以按引用传递并显式制作副本:
两种形式是等效的。
You need to make a new copy of your incoming argument. You can do what you want in several equivalent ways: 1) you could pass-by-value:
or 2) you can pass-by-reference and make a copy explicitly:
both forms are equivalent.
C++ 有比不可变类型更好的东西——
const
。 根据您的需要,单一类型可以是可变的或不可变的。 也就是说,有一些有用的模式来处理短生命周期(近)副本:std::unique_ptr
可以在 C++17 之前以类似的方式使用,尽管该函数可以当然抛出std::bad_alloc
。C++ has something better than immutable types—
const
. A single type can be mutable or not depending on your needs. That said, there are useful patterns for dealing with short-lifetime (near-)copies:std::unique_ptr
may be used in a similar fashion prior to C++17, although the function can then of course throwstd::bad_alloc
.