【问题标题】:Why does pass by reference cause this to crash (C++)?为什么按引用传递会导致崩溃(C++)?
【发布时间】:2020-02-17 21:52:48
【问题描述】:

我遇到了一些奇怪的行为,我不确定该转向哪里。

基本上,我有一组类,其中一个应该由另外两个的实例构成。我正在使用传递引用来分配资源,但第二个分配在我的机器上崩溃了。我不明白为什么第二个任务会崩溃,但第一个工作正常。为了让这更令人困惑,我尝试在在线 cpp 编译器中重新创建问题,但它似乎在那个环境中运行良好。

我隐藏了类名并删除了一些似乎与此问题无关的方法。有人有什么想法吗?

#include <iostream>

using namespace std;

class Driver{};
class ITransmission{};
class ManualTransmission : public ITransmission {};

class Car
{
public:
    Car(ITransmission &trans, Driver &driver);

private:
    ITransmission *m_trans;
    Driver *m_driver;
};

Car::Car(ITransmission &trans, Driver &driver)
{
    *m_trans = trans;
    *m_driver = driver; // <-- **** Crashes here!?!? ****
}

int main()
{
    ITransmission *trans = new ManualTransmission();
    Driver *driver = new Driver();
    Car car(*trans, *driver);

    return 0;
}

【问题讨论】:

  • *m_driver 的意思是“转到存储在m_driver 中的地址并获取那里的值。”现在问问自己:当您尝试取消引用 m_driver 时,它指向哪里?
  • m_trans 和 m_driver 不指向任何东西,你的代码有 UB。它与通过引用传递无关。
  • 感谢您通过正确的演示示例提出明确的问题!我不会回答,因为人们已经在 cmets 中回答了。顺便说一句,here 提到您的玩具模型不需要指针;可能你的真实代码也不需要它们。
  • @Borgleader 这是有道理的,我认为它会起作用,因为它正在分配取消引用的值,但我想现在我想这并没有真正的意义。因此,如果我想用预初始化的 Driver 和 Transmission 对象构造 Car,我是否需要使用 Car(ITransmission *trans, Driver *driver); 之类的东西,然后使用 m_trans = trans 分配成员?
  • @eeScott ITransmissionDriver 对象在 Car 对象中的预期生命周期是多少?他们会不会被转移到另一个Car?或者它们是否存在于Car 的整个生命周期中,并且只存在于这个Car 中?

标签: c++


【解决方案1】:

*m_trans*m_drivers 只是指针 指向它们各自的类型。它们本身不是对象。在您的复制构造函数中,您正在调用

*m_trans = trans

因为m_trans 没有指向任何东西而你正在取消引用它而崩溃。 你想要的是,

m_trans = &trans
m_driver = &driver

这会将 指针 设置为指向您传入的对象的地址,而在您尝试分配给指向的对象之前。

【讨论】:

  • 与将构造函数的签名更改为Car(ITransmission *trans, Driver *driver); 然后使用m_trans = trans 分配成员相比,按照您的建议进行操作有什么好处吗?
  • @eeScott 两者完全相同。但是,请注意,如果您传入的那些指针或引用变得无效,您将再次回到未定义行为领域。我强烈建议让Car 自己管理内存。
  • 并非如此。写完答案后,我看到了您的评论。您现在正在进入对用户来说“更具可读性”的领域。有时人们更喜欢通过指针传递,有时人们更喜欢通过引用传递。我想在您的特定情况下使用按指针传递有一点优势,这样您就不必在调用函数时取消引用指针,但这开始变得挑剔了。
  • 我尝试了这两种解决方案,它们似乎工作相同,所以我认为这是可能的。实际上,我开始走这条路是因为我希望能够为单元测试目的而剔除传输和驱动程序。如果我有 Car 做它自己的内存管理,我不知道有什么方法可以删除这些成员。
  • @eeScott 您的用例可能需要使用pimpl idiom。我用它所有的时间。不过它有一点皱纹,描述为here
猜你喜欢
  • 1970-01-01
  • 2021-06-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-17
相关资源
最近更新 更多