![]() |
1
41
第二种方法更为惯用和富有表现力。在读取代码时,很明显函数在参数上没有前提条件(它没有参数),并且它实际上会在内部创建一个对象。对于随便的读者来说,第一种方法并不那么清楚。调用意味着对象将被更改(通过引用传递),但如果传递的对象上有任何前提条件,则不太清楚。 关于副本。您发布的代码不使用赋值运算符,而是使用复制构造。C++定义了 return value optimization 它在所有主要编译器中实现。如果您不确定是否可以在编译器中运行以下代码段:
使用G++您将得到一行 x::() . 编译器在堆栈中为 X 对象,然后调用构造 川芎嗪 结束 X (实际上) 川芎嗪 是 X . 里面的操作 F-() 直接应用于 X ,相当于第一个代码段(按引用传递)。 如果您没有使用复制构造函数(您是否编写了: xx;x= f-(); )然后它会同时创建 X 和 川芎嗪 并应用赋值运算符,生成三行输出: x::() / x::() / X::算符= . 所以在某些情况下效率可能会低一点。 |
![]() |
2
11
使用第二种方法。看起来效率较低,但是C++标准允许拷贝被规避。此优化称为 Named Return Value Optimization 并在大多数当前的编译器中实现。 |
![]() |
3
3
是的,在第二种情况下,它将生成对象的副本,可能是两次—一次从函数返回值,然后再次将其分配给main中的本地副本。有些编译器会优化第二个副本,但一般来说,您可以假设至少会发生一个副本。 但是,为了清晰起见,您仍然可以使用第二种方法,即使对象中的数据很大,但不必牺牲正确使用智能指针的性能。查看boost中的智能指针类套件。这样,即使外部对象是,内部数据也只分配一次,永远不会复制。 |
![]() |
4
2
避免的方法 任何 复制是为了提供一个特殊的构造函数。如果你 可以重新编写代码,使其看起来像:
如果fillmoughly()返回数据(可能是“大字符串”,那么就有一个采用“大字符串”的构造函数。如果您有这样一个构造函数,那么编译器将非常喜欢构造一个对象,而不进行任何复制来执行返回。当然,这在现实生活中是否有用取决于你的具体问题。 |
![]() |
5
2
有点惯用的解决方案是:
|
![]() |
6
0
或者,您可以通过让对象获取自己的数据,即通过
|
![]() |
7
0
根据对象的实际大小和操作的频率,不要过于拘泥于效率,因为这两种方式都不会产生明显的效果。只有在确定有必要时,才应以牺牲干净、可读的代码为代价进行优化。 |
![]() |
8
0
当您通过复制返回时,一些循环可能会被浪费。是否值得担心取决于对象的实际大小以及调用此代码的频率。
但我想指出,如果
这也浪费了几个周期。重新编写代码为
对您来说可能是双赢的:您可以将largeobj实例初始化为已知和有用的状态,并且可以减少浪费的周期。
如果你不总是想用
更新
(来自您的编辑和注释):从语义上讲,如果值得为创建typedef
只有您可以确定这是否适合您的应用程序。我的观点是即使
|
![]() |
9
-1
当您在一个dll中实现getobjdata(),从另一个dll调用它,并且这两个dll在同一语言中以不同语言或编译器的不同版本实现时,第一个代码段尤其有用。原因是,当它们在不同的编译器中编译时,它们通常使用不同的堆。必须在同一堆中分配和释放内存,否则会损坏内存。
但是,如果您不这样做,我通常只返回一个指针(或智能指针)来存储您的函数分配的内存:
…除非我有特别的理由不这么做。 |
![]() |
AstralHex · 矩阵乘法代码工作不正常 6 月前 |
![]() |
Fishie · 作为类成员的智能指针是否仍然自动释放?[关闭] 6 月前 |
![]() |
Die4Toast · 递归调用成员箭头运算符-> 6 月前 |
![]() |
Anka Hanım · 关于结构和动态数组地址的问题 6 月前 |