【问题标题】:How can I use more parameters in a new call?如何在新调用中使用更多参数?
【发布时间】:2014-02-10 06:06:43
【问题描述】:

抱歉,如果“新调用”不是 C++ 术语。如果不是,请告诉我正确的术语是什么。我是一名从 C++ 开始的 C 程序员。我有struct A,我想使用new 运算符中的参数对其进行初始化。像这样:

A* a = new A(foo, baa);

所以,我尝试使用它定义函数:void* A::operator new(T a, T B) { ... }

但我得到一个编译器错误:

error: 'operator new' takes type size_t ('unsigned int') as first parameter

另外,不确定是否相关,但是size_t类型的重载参数的函数已经定义了,像这样:

void* A::operator new(size_t size) { ... }

【问题讨论】:

  • 最好的方法是A a(foo, baa);,但您不需要提供new 重载;已经内置了一个。
  • 你想重载operator new(创建你自己的内存分配器)还是只想给A一个带有两个参数的构造函数...?
  • @chris: 就像通常的方法一样?另一个相关的问题:此方法能否返回与A*void* 不同的类型?
  • @dvnrrs:最后一个选项:A 一个接受两个参数的构造函数...抱歉,如果我不够清楚。
  • 嗯,我一直在支持这个问题,因为在整个视图中(所有当前的 3 个答案),它为一个叛逆的 c 程序员提供了一个很好的画面,重载有什么区别@ 987654335@ vs 编写构造函数。如果全部合并,可能是规范的候选者。

标签: c++ constructor operator-overloading


【解决方案1】:

您不需要为此重载operator new。你只需要一个构造函数:

class A
{
    public:
        A(FooType foo, BaaType baa);
};

A::A(FooType foo, BaaType baa)
{
    // initialize object here
}

然后你可以写(假设你已经获得了FooType类型的变量foo等等):

A *a = new A(foo, baa);

【讨论】:

  • 我会试试的。它也适用于struct,对吗?我不知道 C++ classstruct 有多少不同。无论如何,谢谢
  • @TheMask classstruct 在 c++ 中是完全等价的,唯一的区别是默认的成员保护策略。
  • @TheMask 它适用于struct。它们在 C++ 中几乎相同。 (C++ 中唯一的区别是 class 中的成员默认是私有的;在 struct 中它们默认是公共的;继承的 struct 默认是公共的,而继承的类是私有的。)跨度>
【解决方案2】:

在 C++ 中的实现方式是为 A 提供一个非默认构造函数。

struct A {
  int a;
  int b;
  explicit A(int a_, int b_) : a(a_), b(b_) {}
};

...
A * a = new A(1, 2);
assert(a->a == 1);
assert(a->b == 2);

冒号 (:) 后面的表达式是构造函数的初始化列表——它们在构造过程中执行成员的初始化。它们通常比 C 风格的变体更有效:

A::A(int a_, int b_) { a = a_; b = b_; }

在惯用的 C++ 中,您总是希望尽可能使用初始化列表。你也不想使用裸指针,所以最好写:

std::shared_ptr<A> a(new A(1, 2));
// or
std::unique_ptr<A> a(new A(1, 2));

shared_ptr 用于多个实体可能需要持有该实例并且没有明确的范围应该存在的情况。 unique_ptr 用于对象应该存在的明确范围时。 unique_ptr 超出范围时将 delete a。当最后一个引用给定对象的shared_ptr 超出范围时,shared_ptr 将执行删除。

使用explicit 关键字的原因是为了防止在自动转换中使用给定的构造函数。在 C++11 之前的版本中,它对多参数构造函数没有影响。但在C++11中,当you use brace intialization时有效。

【讨论】:

  • 看起来正是我要找的东西。我会试试的。谢谢
  • @πάνταῥεῖ 为什么要为此 +1?它可能只会混淆OP。一步一步来。他甚至还没有弄清楚构造函数。
  • @dvnrrs 因为explicit 在答案的第一个版本中值得一提(当然现在仍然如此)。实际版本可能会使没有经验的 c -> c++ 熟练者感到困惑,但我不觉得 OP 是一个......(顺便说一句,我也一直在支持你的答案)
  • @KubaOber 您的答案看起来最好进行编辑,以便对 OP 的问题/误解给出规范的答案。您可以将其他答案的各个方面整合到您的答案中,并为贡献点赞。
【解决方案3】:

您需要区分new 运算符和构造函数:new 运算符的作用不亚于malloc(),它们分配了一小块内存。然后构造函数初始化该内存,使其成为A 类型的有效对象。

您的困惑源于new 关键字同时执行分配和构造的事实。线

A* foo = new A(...);

首先调用new 运算符来获取内存,然后调用适当的构造函数,将给定的参数传递给它,以构造对象。

因此,正如其他人已经指出的那样,您需要添加一个带有所需参数的构造函数,而不是 new 运算符:

class A {
public:
    A(int arg1, int arg2);
    int member1, member2;
};

A::A(int arg1, int arg2) : member1(arg1), member2(arg2) {
    //Do additional stuff that cannot be achieved by calling the constructors of the members alone.
}

注意,在这段代码中,你显式调用了初始化列表中A的数据成员的构造函数(:{之间的部分。

【讨论】:

  • newmalloc 完全不同;它调用类型的构造函数,malloc 没有。 (我确定这就是您的意思,但我们需要小心不要误导显然刚刚起步的 OP。)
  • @dvnrrs 对不起,你错了。所有operator new() 定义仅提供内存。他们甚至没有获得调用构造函数所需的参数。效果确实是malloc() 加上那个异常的东西。 operator new() 在一个类中的唯一优点是,您可以使用不同的方法来分配不同类的对象。
  • @dvnrrs '构造函数然后初始化......'他正确地提到了差异(检查placement new)。
  • @cmaster 是的,我意识到用户定义的operator new 重载不会直接调用ctor。但从用户的角度来看,使用new 会导致调用ctor,不像malloc
猜你喜欢
  • 2020-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多