【问题标题】:c++ named parameter idiom - string property not setc++ 命名参数习语 - 未设置字符串属性
【发布时间】:2019-03-20 22:56:21
【问题描述】:

请考虑以下(简单)代码。奇怪的 (?) 行为在 main() 例程中,详情如下。

数据类

Packet.h

#include <string>

class Packet {
public:
    Packet(int iParam, std::string sParam);
    ~Packet();
    void setInt(int iParam);
    void setString(std::string sParam);

private:
    int iProperty_;
    std::string sProperty_;
};

Packet.cpp

#include "Packet.h"
using std::string;

Packet::Packet(int iParam, string sParam) : iProperty_(iParam), 
    sProperty_(sParam) {}
Packet::~Packet() {}

void Packet::setInt(int iParam) {
    iProperty_ = iParam;
}
void Packet::setString(std::string sParam) {
    sProperty_ = sParam;
}

控制器类

PacketController.h

#include <string>

class PacketController {
public:
    PacketController();
    ~PacketController();
    PacketController & andSetInt(int iParam);
    PacketController & andSetString(std::string sParam);

private:
    Packet packet_;
};

PacketController.cpp

#include "PacketController.h"
using std::string;

PacketController::PacketController() : packet_(0, "") {}
PacketController::~PacketController() {}

PacketController & PacketController::andSetInt(int iParam) {
    packet_.setInt(iParam);
    return *this;
}

PacketController & PacketController::andSetString(string sParam) {
    packet_.setString(sParam);
    return *this;
}

main()

int main() {
    PacketController& ctrlRef = PacketController()
        .andSetString("hello world")
        .andSetInt(19);

    PacketController ctrlVal = PacketController()
        .andSetString("hello world")
        .andSetInt(19);

    PacketController& ctrlRef2 = PacketController();
    ctrlRef2.andSetString("hello world")
        .andSetInt(19);

    return 0;
}

如果在main()return 0; 行暂停执行,则在内部packet_ 对象上可以看到以下值:

ctrlRef - packet_:iProperty_: 19 sProperty_: ""

ctrlVal - packet_:iProperty_: 19sProperty_: "hello world"

ctrlRef2 - packet_:iProperty_: 19sProperty_: "hello world"

那么为什么ctrlRef 中的packet_ 对象上的sProperty_ 为空?与 PacketController 对象初始化时的引用有关吗?但是,为什么ctrlRefpacket_ 对象上的iProperty_ 正确设置为19

【问题讨论】:

  • ymmv,但我认为命名参数习语带来了大量样板文件,但收益甚微,如果您只使用 struct params { /*all params that you want to pass (with their names) */} 并创建构造函数,则可以在调用站点上显示参数名称采取params
  • 您的编译器应该警告您所显示的代码。如果没有,则启用更多警告。
  • @1: 必须查找 'ymmv' :) 一些示例代码?上面的客户端代码很酷
  • @2:Visual Studio 上默认没有警告,运行时执行似乎没有任何问题...(除了缺少字符串)

标签: c++ parameters reference idioms named


【解决方案1】:
PacketController& ctrlRef = PacketController()
    .andSetString("hello world")
    .andSetInt(19);

ctrlRef 是对其生命周期在完整表达式评估结束时结束的临时对象的引用(就在; 处)。 ctrlRef2也是如此。

使用它会产生undefined behavior

另一方面,ctrlVal 是从临时初始化的值。用起来没问题。

【讨论】:

  • There are ways... 但最好使用std::unique
  • 谢谢 - 上面 GotW 的有用链接。值得注意的是,对const 的引用可以绑定到一个临时的 - 虽然上面没有太多用处......
猜你喜欢
  • 2010-09-17
  • 1970-01-01
  • 1970-01-01
  • 2012-03-21
  • 1970-01-01
  • 2011-08-26
  • 2019-03-12
  • 2010-12-31
  • 2014-12-12
相关资源
最近更新 更多