问一个简单的 C++关于构造函数和 new 表达式的问题

2018-10-27 18:36:26 +08:00
 XuanFei990

1、为什么 CB 类可以使用 CB b1 = new CB();的方式,CA 和 CC 提示类型不符,这个从 new 的返回类型是 void*可以知道原因; CB 可以这么写仅仅因为构造函数传递的是 void* ??就可以从 CB*转换为 CB 类型么?

2、为什么 b1 会调用两次 CB 的构造函数??从生成的汇编代码上确实看到,调用了两次构造;但是在 Test 函数结束后,只是少调用了一次 CB 析构函数,前边一共有 4 次 CB 的构造函数,在 Test 函数结束后,只看到了 3 次 CB 的析构函数这是为什么?使用 delete b1 是语法错误,因为 b1 不是指针类型。

环境
VS2017 + C++14 语言的设置

class CA
{
public:
    CA() { std::cout << "Class A" << std::endl; }; //无参构造函数
    ~CA() { std::cout << "Class A die..." << std::endl; };
};
class CB
{
public:
    CB(void* pVOID = NULL) { std::cout << "Class B" << std::endl; }; //构造需要传递指向 void 类型的指针,默认为 NULL
    ~CB() { std::cout << "Class B die..." << std::endl; };
};
class CC
{
public:
    CC(int* pLength = NULL) { std::cout << "Class C" << std::endl; } //构造需要传递指向 int 类型的指针,默认为 NULL
    ~CC() { std::cout << "Class C die..." << std::endl; };
};

void Test(void)
{
    CA  a0;
    //CA  a1 = new CA();  //缺少合适构造函数,使 CA* 转换为 CA
    CA* a2 = new CA();

    CB  b0;
    CB  b1 = new CB(); //为什么这里就可以这么使用呢?并且从运行结果上看执行了两次 CB 的构造函数?
    CB* b2 = new CB();

    CC  c0;
    //CC  c1 = new CC(); //缺少合适构造函数,使 CC*转换为 CC
    CC* c2 = new CC();

    delete a2;
    //delete b1; //不是 CB*类型
    delete b2;
    delete c2;
}
2302 次点击
所在节点    C
8 条回复
wevsty
2018-10-27 19:18:19 +08:00
new CB();调用了第一次构造函数返回的类型是 CB*,所有的指针都可以转换为 void*类型,所以编译器帮你使用了 CB 的构造函数,把 new CB()得到的指针作为参数传递进去了,所以 b1 这个对象也不是 new 出来的,你当然也不能对他 delete。这个是隐性的数据类型转换导致的结果。
XuanFei990
2018-10-27 19:50:34 +08:00
@wevsty 1、调用了两次构造函数,是构造了两个完整的对象么?一次在堆中构造,一次在栈中构造?
2、作为参数传递进去,意思是在 CB 的构造函数中可以通过 pVOID 来访问到第一次构造的对象?

最近在看一个别的公司提供的一个操作 USB Device 的 API 源码,,构造函数就是形如这个的,只不过是用的 HANDLE,实际上也是通过 typedef 把 void*起了个别名,在测试的时候,发现这么写居然也可以通过编译

实际应用中,CB b1 = new CB();这种写法有什么后遗症么??

正常应该使用 CB* b1 = new CB();这种方式对么?
nicebird
2018-10-27 20:21:32 +08:00
CB b1 = new CB();
等价于
CB *temp = new CB();
CB b4(temp);

1. 发送了一次隐式转换,然后构造,为了防止这种现象使用 explicit 关键字。
2. temp 没有被释放掉。产生了内存泄漏。
justou
2018-10-27 20:28:42 +08:00
不该隐式转换的都尽量避免, 构造器加 explicit 修饰, 尤其是单参数的构造器.
后遗症就是容易出现这种隐式转换导致的各种奇怪 bug
innoink
2018-10-27 20:42:37 +08:00
你只要搞明白,为什么第一个 new CB 内存泄漏了,就全明白了
XuanFei990
2018-10-27 23:00:33 +08:00
@justou 哦,这样,那明白了,,那就是这个 API,实际上是有潜在 bug,最好应该加上 explicit ?防止这种隐式转换是么?
XuanFei990
2018-10-27 23:01:59 +08:00
@nicebird 嗯,明白了,刚开始看高级特性,知道遇到的少了些。。。以前都是当 C 用的。。。
f4nyc
2018-10-27 23:11:04 +08:00
不是 ub 吗……

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/501734

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX