【问题标题】:C++ create new pointer from existing valueC ++从现有值创建新指针
【发布时间】:2026-01-16 07:20:06
【问题描述】:

如何从值参数创建指针?

尝试 1

template<typename T1, typename T2>
class Both {
public:
  T1 *lx;
  T2 *rx;
  Both(T1 _lx, T2 _rx) {
    lx = new T1;
    rx = new T2;
    *lx = _lx;
    *rx = _rx;
  }
  ~Both() {
    delete lx;
    delete rx;
  }
};

class cls {
public:
  int x;
  cls(int v) : x(v) {}
};

Both<cls, cls> b(cls(1), cls(2));

这会导致错误

错误:'cls' 的初始化没有匹配的构造函数 lx = 新 T1;

我不想强制 Both 的所有参数必须有一个默认的空构造函数。

尝试 0

在此之前,我尝试将Both 实现为

Both(T1 _lx, T2 _rx) : lx(&_lx) rx(&_rx) {}

我收到了警告

警告:使用参数“_rx”的堆栈地址初始化指针成员“rx”[-Wdangling-field] 两者(T1 _lx, T2 _rx) : lx(&_lx), rx(&_rx) {}

尝试 2

Both(T1 _lx, T2 _rx) {
  lx = (T1*) malloc (sizeof(T1));
  rx = (T2*) malloc (sizeof(T2));
  *lx = _lx;
  *rx = _rx;
}

发出中止信号

FAILED: {Unknown expression after the reported line} 由于致命错误情况: SIGABRT - 中止(异常终止)信号

我对@9​​87654327@ 的预期用例是让用户在完成后手动调用delete

因此重申一下,如何将从参数传递的非指针值转换为指针?

【问题讨论】:

  • 当类全是指针但没有值时,为什么要按值传递?您正在存储指向构造函数参数的指针,即一旦构造函数返回,它们就是无效指针
  • 为什么要手动delete?您的代码与The Rule of Three不兼容,所以在复制Both的对象时可能会造成一些麻烦。

标签: c++ pointers arguments


【解决方案1】:
  1. 分配一个新对象
  2. 在那里复制参数的值
  3. 将指针分配给成员
Both(T1 _lx, T2 _rx) : lx(new T1(_lx)), rx(new T2(_rx)) {}

【讨论】:

    【解决方案2】:

    假设您的类型是可复制的,那么您在第一次尝试时几乎就在那里。

    lx = new T1{_lx};
    

    这个应该确实有效。或者 - 如果您的类型不可复制 -

    lx = new T1{std::move(_lx)};
    

    但是,您应该注意您的课程不符合rule of three。在这种情况下,您最好的选择是使用智能指针,例如 std::unique_ptrstd::shared_ptr。通常,除非您正在设计自己的智能指针或容器,否则根本不应该使用new

    【讨论】:

      【解决方案3】:

      cls 的唯一构造函数是采用 int 的构造函数,new 必须在新分配的内存块上调用构造函数。通过定义cls::cls(int),您阻碍了cls::cls() 的生成——默认构造函数,因此在不提供构造函数参数的情况下无法调用new。第二次尝试能够编译(尽管仍然无法正常工作),因为没有调用构造函数,并且 malloc() 根本不调用构造函数。

      【讨论】:

        【解决方案4】:
        lx = new T1;
        rx = new T2;
        

        这里使用了什么构造函数? 这不是你提供的cls(int v) : x(v) {},因为这个确实需要int v

        解决方案是使用默认构造函数、void 构造函数或将所有参数设置为默认值的构造函数。

        • cls(int v = 0) : x(v) {} // 所有参数都设置为默认值的构造函数
        • cls() = 默认值; // 默认构造函数
        • cls():x(0){} // 一个 void 构造函数

        选择任何一个,但只能选择一个。

        【讨论】:

          【解决方案5】:

          感谢您提供的所有见解,我仍然不熟悉 C++ 开发的标准,因此非常感谢您的所有反馈。

          我选择了一个不需要非指针值到指针转换的解决方案,并尝试坚持三类规则

          template <typename T1, typename T2>
          class Both
          {
          public:
            T1 lx;
            T2 rx;
            Both(T1 _lx, T2 _rx) : lx(_lx), rx(_rx) {}
          };
          

          我可以简单地为指针执行以下操作

          cls *x = new cls(1);
          cls *y = new cls(2);
          Both<cls*, cls*> b(x, y);
          REQUIRE((b.lx)->x == 1);
          REQUIRE((b.rx)->x == 2);
          

          【讨论】: