Item 46. Forwarding Functions

优化转发函数
本文探讨了如何优化转发函数,重点介绍了传递参数的方式以及内联函数的选择。通过改进传递方式和合理使用内联,可以显著提高效率。

Item 46. Forwarding Functions

Difficulty: 3

What's the best way to write a forwarding function? The basic answer is easy, but we'll also learn about a subtle change to the language made shortly before the standard was finalized.

Forwarding functions are useful tools for handing off work to another function or object, especially when the hand-off is done efficiently.

Critique the following forwarding function. Would you change it? If so, how?

// file f.cpp 
//
#include "f.h"
/*...*/
bool f( X x )
{
  return g( x );
  
}

 

Solution

graphics/bulb_icon.gif

Remember the introduction to the question? It was: Forwarding functions are useful tools for handing off work to another function or object, especially when the hand-off is done efficiently.

This introduction gets to the heart of the matter梕fficiency.

There are two main enhancements that would make this function more efficient. The first should always be done; the second is a matter of judgment.

  1. Pass the parameter by const& instead of by value.

    "Isn't that blindingly obvious?" you might ask. No, it isn't, not in this particular case. Until as recently as 1997, the draft C++ language standard said that because a compiler can prove that the parameter x will never be used for any other purpose than passing it in turn to g(), the compiler may decide to elide x completely (that is, to eliminate x as unnecessary). For example, if the client code looks something like this:

    X my_x; 
    f( my_x );
    

    then the compiler used to be allowed to either:

    • Create a copy of my_x for f()'s use (this is the parameter named x in f()'s scope) and pass that to g()

    • Pass my_x directly to g() without creating a copy at all, because it notices that the extra copy will never be used except as a parameter to g()

      The latter is nicely efficient, isn't it? That's what optimizing compilers are for, aren't they?

      Yes and yes, until the London meeting in July 1997. At that meeting, the draft was amended to place more restrictions on the situations in which the compiler is allowed to elide "extra" copies like this. This change was necessary to avoid problems that can come up when compilers are permitted to wantonly elide copy construction, especially when copy construction has side effects. There are reasonable cases in which reasonable code may legitimately rely on the number of copies actually made of an object.

      Today, the only situation in which a compiler may still elide copy constructors is for the return value optimization (see your favorite textbook for details) and for temporary objects. This means that for forwarding functions like f(), a compiler is now required to perform two copies. Because we (as the authors of f()) know in this case that the extra copy isn't necessary, we should fall back on our general rule and declare x as a const X& parameter.

      Guideline

      graphics/guideline_icon.gif

      Prefer passing objects by reference instead of by value, using const wherever possible.


      Note: If we'd been following this general rule all along instead of trying to take advantage of detailed knowledge about what the compiler is allowed to do, the change in the rules wouldn't have affected us. This is a stellar example of why simpler is better梐void the dusty corners of the language as much as you can, and strive never to rely on cute subtleties.

      Guideline

      graphics/guideline_icon.gif

      Avoid the "dusty corners" of a language; use the simplest techniques that are effective.


  2. Inline the function. This one is a matter of judgment. In short, prefer to write all functions out-of-line by default, and then selectively inline individual functions as necessary only after you know that the performance gain from inlining is actually needed.

Guideline

graphics/guideline_icon.gif

Avoid inlining or detailed tuning until performance profiles prove the need.


If you inline the function, the positive side is that you avoid the overhead of the extra function call to f().

The negative side is that inlining f() exposes f()'s implementation and makes client code depend on it so that if f() changes, all client code must recompile. Worse, client code now also needs at least the prototype for function g(), which is a bit of a shame because client code never actually calls g() directly and probably never needed g()'s prototype before (at least, not as far as we can tell from our example). And if g() itself were changed to take other parameters of still other types, client code would now depend on those classes' declarations, too.

Both inlining and not inlining can be valid choices. It's a judgment call in which the benefits and drawbacks depend on what you know about how (and how widely) f() is used today, and how (and how often) it's likely to change in the future.

内容概要:本文档围绕六自由度机械臂的ANN人工神经网络设计展开,涵盖正向与逆向运动学求解、正向动力学控制,并采用拉格朗日-欧拉法推导逆向动力学方程,所有内容均通过Matlab代码实现。同时结合RRT路径规划与B样条优化技术,提升机械臂运动轨迹的合理性与平滑性。文中还涉及多种先进算法与仿真技术的应用,如状态估计中的UKF、AUKF、EKF等滤波方法,以及PINN、INN、CNN-LSTM等神经网络模型在工程问题中的建模与求解,展示了Matlab在机器人控制、智能算法与系统仿真中的强大能力。; 适合人群:具备一定Ma六自由度机械臂ANN人工神经网络设计:正向逆向运动学求解、正向动力学控制、拉格朗日-欧拉法推导逆向动力学方程(Matlab代码实现)tlab编程基础,从事机器人控制、自动化、智能制造、人工智能等相关领域的科研人员及研究生;熟悉运动学、动力学建模或对神经网络在控制系统中应用感兴趣的工程技术人员。; 使用场景及目标:①实现六自由度机械臂的精确运动学与动力学建模;②利用人工神经网络解决传统解析方法难以处理的非线性控制问题;③结合路径规划与轨迹优化提升机械臂作业效率;④掌握基于Matlab的状态估计、数据融合与智能算法仿真方法; 阅读建议:建议结合提供的Matlab代码进行实践操作,重点理解运动学建模与神经网络控制的设计流程,关注算法实现细节与仿真结果分析,同时参考文中提及的多种优化与估计方法拓展研究思路。
是的,**你找到问题的关键原因了!** 你的系统中: ```bash sysctl net.ipv6.conf.br0.forwarding = 0 sysctl net.ipv6.conf.ens33.forwarding = 0 ``` 表示: - `br0` 桥接接口 **未启用 IPv6 转发**; - `ens33` 物理网卡也 **未启用 IPv6 转发**; --- ### 🔍 为什么这会导致虚拟机收不到 NS? 在 Linux 中,即使使用桥接模式(bridge),**IPv6 的 Neighbor Solicitation(NS)等控制报文也会受到内核网络栈的控制**。如果 `forwarding` 设置为 `0`,系统会认为这是一个**终端设备**,不会转发 IPv6 报文(包括 NS、NA、RA 等)。 这意味着: - 即使 VMware 正确桥接; - 即使 ens33 收到了 NS; - Linux 内核也不会将这些 NS 转发给桥接设备 `br0` 或虚拟机; --- ### ✅ 解决方案: #### 1. **临时启用 IPv6 转发:** ```bash sysctl -w net.ipv6.conf.br0.forwarding=1 sysctl -w net.ipv6.conf.ens33.forwarding=1 ``` #### 2. **永久生效(写入配置文件):** 编辑 `/etc/sysctl.conf` 或 `/etc/sysctl.d/99-ipv6.conf`(推荐): ```conf net.ipv6.conf.br0.forwarding = 1 net.ipv6.conf.ens33.forwarding = 1 ``` 然后应用配置: ```bash sysctl -p # 或者如果你使用了 /etc/sysctl.d/ sysctl --system ``` --- ### ✅ 额外建议: - 同时检查 `accept_ra` 是否允许接收 Router Advertisement: ```bash sysctl net.ipv6.conf.br0.accept_ra ``` 推荐设为 `2`: ```bash sysctl -w net.ipv6.conf.br0.accept_ra=2 ``` - 可选:关闭桥接设备的 STP(生成树协议)以避免广播帧被丢弃: ```bash brctl stp br0 off ``` --- ### ✅ 验证方式: 1. 使用 `tcpdump` 抓包验证 NS 是否到达 `br0`: ```bash tcpdump -i br0 -nn icmp6 ``` 2. 检查虚拟机是否能正常收到 NS 并响应 NA。 --- ### ✅ 总结: | 设置项 | 当前值 | 推荐值 | 说明 | |--------|--------|--------|------| | `net.ipv6.conf.br0.forwarding` | 0 | 1 | 控制 br0 是否转发 IPv6 流量 | | `net.ipv6.conf.ens33.forwarding` | 0 | 1 | 控制 ens33 是否转发 IPv6 流量 | | `net.ipv6.conf.br0.accept_ra` | 0/1/2 | 2 | 控制是否接受 RA 并自动配置地址 | ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值