在 C/C++ 中使用堆栈进行内存管理时的编码风格
来自 Java 背景,我试图学习如何以最简单的方式处理 C/C++ 中的内存分配(取消)分配。
一位同事建议我只为成员变量分配内存,让堆栈处理局部变量。我不完全确定这个概念叫什么,但这意味着函数将像这样实现:
void inc(int x, int &y){
y=x+1;
}
另一种方式是这样的:
int inc(int x, int &y){
y=x+1;
return y;
}
第一个禁止我在表达式中使用它,即:
int y;
inc(2,y);
inc(y,y);
第二个可以,但它不是' t Pretty:
int y;
y=inc(inc(2,y),y);
在我搞乱我的代码之前,经验丰富的 C/C++ 程序员对这种编码风格有何看法?
Coming from a Java background, I'm trying to learn how to handle memory (de)allocation in C/C++ in the simplest way.
A colleague suggested that I only allocate memory for member variables and let the stack handle the local variables. I'm not entirely sure what this concept is called, but it means that functions would be implemented like this:
void inc(int x, int &y){
y=x+1;
}
Another way would be this:
int inc(int x, int &y){
y=x+1;
return y;
}
First one prohibits me from using it in an expression, i.e:
int y;
inc(2,y);
inc(y,y);
Second one does, but it isn't pretty:
int y;
y=inc(inc(2,y),y);
Before I go mess up my code, what do seasoned C/C++ programmers think about this coding style?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
对于使用此函数的程序员来说,我强烈劝阻他们
,不清楚为什么该函数会修改输入并返回值,并且它们都是同一个对象。
实际上,在我看来,选择是:
和
在一般情况下,我仍然更喜欢
#2
因为我发现“输出参数”过时且使用起来很笨拙。正如您所指出的,您最终会与表达式作斗争,并且调用函数1时实际发生的情况并不是很清楚。再说一遍,如果您有一个比 int 更复杂的对象(例如,一个数组或一个大类,或者您只想“返回”多个对象),它可能会使对象所有权变得更容易如果您不在函数内创建任何新对象,则需要处理,使
#1
成为更方便的选择。我认为我在这里试图得出的结论是,它取决于场景。试图对这些事情进行概括是愚蠢的行为。
1 - 使用指针而不是引用在一定程度上解决了这个问题,尽管它确实引入了膨胀,现在不得不费心检查无效指针:
I would heavily discourage
To the programmer using this function, it's not clear why the function modifies an input, and returns the value, and they're both the same object.
Really, to my mind, the choice is between:
and
In the general case, I still prefer
#2
as I find "out parameters" archaic and clunky to use. As you point out, you end up struggling with expressions and it's not terribly clear what's actually going on when you invoke the function1.Then again, if you have an object more complex than
int
(say, an array, or a large class, or you just want to "return" more than one object), it may make object ownership easier to deal with if you're not creating any new objects inside the function, making#1
the more convenient choice.I think the conclusion I'm trying to draw here, is that it depends on the scenario. Trying to generalise about these things is a fool's errand.
1 - Using pointers rather than references solves that somewhat, though it does introduce bloat with now having to bother checking for invalid pointers:
还有第三种更简单的方法:
There is a third much simpler way:
这不太可能是您同事所指的编程风格。像整数或简单结构这样的 POD 类型不是您通常关心的数据。 资源获取即初始化,即 RAII,是 C++ 中的一种常见策略,它利用了堆栈分配的属性变量,从而保证在大多数情况下调用其析构函数。
假 RAII 代码:
This is not likely the style of programming your colleague was referring to. POD types like integers or simple structs are not the data you are usually concerned with. Resource Acquisition is Initialization, or RAII, is a common strategy in C++ which utilizes the property of stack allocated variables whereby their destructor is guaranteed to be called in most situations.
Faux-RAII code:
对于基元类型,这是可以的:
对于更复杂的类型,这样做可以避免函数返回时进行额外的复制
对于堆分配的对象,我建议使用 boost::shared_ptr (tr1::shared_ptr) 库。然后您就可以像在 java 中一样编写代码。
您可以将 boost::shared_ptr 对象视为 java 引用。没有垃圾收集(只是引用计数),因此您必须自己关心周期。
请记住,shared_ptr 比标准指针慢一点。
另外,请务必记住,应避免复制大对象。 否则最好编写
而不是
除非您需要 foo 中的 str 副本,
编写。另一件事是编译器很聪明,会为你做一些优化。例如,reverse_vector 可以写为
此 RVO(返回值优化)非常有用,但有时编译器无法自动执行此操作。这就是为什么我建议在不依赖 RVO 的情况下编写此类函数,除非您在失败时学习。
For primitives types this is ok:
for more complex types do this to avoid additional copying when function returns
For heap allocated object I suggest using boost::shared_ptr (tr1::shared_ptr) library. Then you can code almost the same as you would do in java.
You can treat boost::shared_ptr objects as java references. There is no garbage collection (just reference counting) so you must care about cycles yourself.
Bear in mind that shared_ptr is a bit slower than standard pointer.
Also it is important to remember that you should avoid copying large objects. It is better to write
instead of
unless you need a copy of str in foo.
One more thing is that the compiler is smart and will do some optimizations for you. For example reverse_vector could be written as
This RVO (return value optimization) is very useful but sometimes the compiler fails to do it automatically. That's why I'd suggest to write this kind of functions without relying on RVO unless you learn when it fails.
您的问题与内存分配无关,只是关于按值或按引用传递参数。
该函数将
y
参数作为引用传递,x
参数被复制。我个人认为这种形式可能是令人严重头痛的根源,因为语法并没有偏离值传递。你应该避免它,除非你正在处理物体。我建议这种形式:
Your question has nothing to do with memory allocation, just about passing parameters by value or by reference.
This function passes th
y
parameter as reference, thex
parameter is being copied.I personally think that this form might the source of serious headache, since the syntax does not divert from passing by value. You should avoid it, unless you are dealing with objects. I suggest this form:
我认为在您的第二个示例中,您不希望引用 y ,因此
您应该引用 y
,因为当您在函数内编辑 y 时,它会再次编辑原始内容
y
而不仅仅是本地副本,这不是您想要的。I think that in your second example you don't want a reference to
y
, so instead ofyou should have
because when you edit
y
inside your function it again edits the originaly
and not just a local copy, which isn't what you're going for.