混合常量和非常量引用传递的参数顺序
为了与尽可能使用非成员函数来改进封装的实践保持一致,我已经编写了许多具有如下声明的类:
void auxiliaryFunction(
const Class& c,
std::vector< double >& out);
它的目的是使用 c 的公共成员函数执行某些操作并用输出填充向量。 您可能会注意到,它的参数顺序类似于 Python 成员函数 defauxiliaryFunction(self, out)
。
然而,还有其他合理的方法来选择参数顺序:一种说法是该函数类似于赋值操作,out =auxiliaryFunction(c)
。例如,
char* strcpy ( char* destination, const char* source );
如果我有一个不同的函数,它不类似于非必要的成员函数,即初始化我创建的新对象的函数,那么
void initializeMyObject(
const double a,
const std::vector<double>& b,
MyObject& out);
会使用此习惯用法:因此,为了保持一致性为了缘故,我应该使用与 auxiliaryFunction 中相同的顺序(最后是可变变量)吗?
一般来说,是选择 (non-const , const)
而不是 (const, non-const)
更好,还是只在某些情况下更好?选择其中一项有什么理由吗?或者我应该只选择一项并坚持下去?
(顺便说一下,我知道 Google 风格指南< /a> 建议使用指针而不是非常量引用,但这与我的问题无关。)
In keeping with the practice of using non-member functions where possible to improve encapsulation, I've written a number of classes that have declarations which look something like:
void auxiliaryFunction(
const Class& c,
std::vector< double >& out);
Its purpose is to do something with c
's public member functions and fill a vector with the output.
You might note that its argument order resembles that of a python member function, def auxiliaryFunction(self, out)
.
However, there are other reasonable ways of choosing the argument order: one would be to say that this function resembles an assignment operation, out = auxiliaryFunction(c)
. This idiom is used in, for example,
char* strcpy ( char* destination, const char* source );
What if I have a different function that does not resemble a non-essential member function, i.e. one that initializes a new object I've created:
void initializeMyObject(
const double a,
const std::vector<double>& b,
MyObject& out);
So, for consistency's sake, should I use the same ordering (mutable variable last) as I did in auxiliaryFunction
?
In general, is it better to choose (non-const , const)
over (const, non-const)
, or only in certain situations? Are there any reasons for picking one, or should I just choose one and stick with it?
(Incidentally, I'm aware of Google style guide's suggestion of using pointers instead of non-const references, but that is tangential to my question.)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
STL 算法将输出(非常量)值放在最后。每个人都应该了解 C++ 的先例。
我也倾向于按照从重要到不太重要的顺序对论点进行排序。 (即框的大小先于框边距调整值。)
(但请注意:无论您做什么,都要保持一致!这比选择这样或那样更重要......)
The STL algorithms places output (non-const) values last. There you have a precedent for C++ that everyone should be aware of.
I also tend to order arguments from important, to less important. (i.e. size of box goes before box-margin tweak value.)
(Note though: Whatever you do, be consistent! That's infinitely more important than choosing this or that way...)
可能有帮助的几点:
是的,我喜欢尽可能遵循标准库的参数排序约定的想法。最小意外原则。那么,很好。但是,请记住,C 标准库本身的设计并不是很好,尤其是在查看文件处理 API 时。所以要小心——从这些错误中吸取教训。
const
带有基本算术类型的很少使用,如果你这样做的话会更令人惊讶。STL,即使有其缺陷,在我看来也是一个更好的例子。
最后,请注意,C++ 还有另一个优点,称为“返回值优化”,大多数现代编译器默认启用该优点。我会使用它并重写您的
initializeMyObject
,或者甚至更好,使用类和构造函数。通过常量引用传递比通过值传递 -- 节省大量复制开销(时间和内存损失)
所以,你的函数签名应该更像这样:(
如果可能的话,我可能会想通过
typedef
隐藏std::vector
。)尽可能使用适量的
const
。对于参数,对于函数。您正在向编译器做出承诺(忠实于您的设计),并且每次您偏离诊断时编译器都会帮助您。充分利用您的语言功能和编译器。此外,了解const&
(const-references) 及其潜在的性能优势。Few points that may be of help:
Yes, I like the idea of following the standard library's argument ordering convention as much as possible. Principle of least surprises. So, good to go. However, remember that the C standard library itself is not very well crafted, particularly if you look at the file handling API. So beware -- learn from these mistakes.
const
with basic arithmetic types are rarely used, it'd be more of a surprise if you do.The STL, even with its deficiencies provide, IMO, a better example.
Finally, note that C++ has another advantage called Return Value Optimization which is turned on in most modern compilers by default. I'd use that and rewrite your
initializeMyObject
or even better, use a class and constructors.Pass by const-reference than by value -- save a lot of copying overhead (both time and memory penalties)
So, your function signature should be more like this:
(And I maybe tempted to hide the
std::vector<double>
by atypedef
if possible.)Use a liberal dose of
const
whenever you can. For parameters, for functions. You are making a promise to the compiler (to be true to your design) and the compiler will help you along every time you digress with diagnostics. Make the most of your language features and compilers. Further, learn aboutconst&
(const-refernces) and their potential performance benefits.