C&C++   发布时间:2022-04-03  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了c – 为什么不完整类型的智能指针数据成员和原始指针数据成员在其父级破坏时具有不同的行为?大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。
在以下代码中:

智能指针数据成员pImpl(类Impl)和原始指针pc(CAT类)都是不完整的数据类型,在Widget.h中没有这两个类的定义

//widget.h

#ifndef W_H_
#define W_H_
#include <memory>

class Widget { 
    public:
        Widget();
        ~Widget() {    //
            delete pc; // I kNow I should put ~Widget to .cpp
                       // I just want to show the difference in behavior
                       // between raw pointer and smart pointer(both has incomplete typE)
                       // when widget object destructs 
        }
    private:
        struct Impl; 
        std::shared_ptr<Impl> pImpl;  // use smart pointer
        struct CAT;
        CAT *pc;  //raw pointer
};
#endif

//widget.cpp

#include "widget.h"

#include <String>
#include <vector>
#include <iostream>
using namespace std;
struct Widget::CAT 
{
    std::string name;
    CAT(){Cout<<"CAT"<<endl;}
    ~CAT(){Cout<<"~CAT"<<endl;}
};      


struct Widget::Impl {
    std::string name;
    Impl(){Cout<<"Impl"<<endl;}
    ~Impl(){Cout<<"~Impl"<<endl;}
};


Widget::Widget()  
    : pImpl(std::make_shared<Impl>()),pc(new CAT)
{}

//main.cpp

#include "widget.h"
int main()
{
    Widget w;
}

//输出

对于原始指针数据成员,当小部件对象被破坏时,它的destuctor不会被调用.

而shared_ptr数据成员,其析构函数已被正确调用.

据我了解,在Widget ::〜Widget()中应该生成一些
代码自动如下:

~Widget() {
            delete pc; // wrote by me

            // generated by compiler
            delete pImpl->get();
        }

为什么在widget被破坏的时候,shared_ptr数据成员和原始数据成员有不同的行为?

我在Linux中使用g 4.8.2测试代码

================================编辑================= ==============
根据答案,原因是因为:

编译器生成代码不是:

~Widget() {
            delete pc; // wrote by me

            // generated by compiler
            delete pImpl->get();
        }

它可能是这样的

~Widget() {
            delete pc; // wrote by me

            // generated by compiler
            pimpl.deleter(); //deleter will be initailized while pimpl object is initialized
        }

解决方法

因为您在头文件中转发声明“CAT”,所以您的数据类型不完整.使用这些信息,编译器将进入未定义的行为,析构函数可能不被调用.

什么标准说

在这里可以找到详细的说明:Why,really,deleting an incomplete type is undefined behaviour?
只需将struct声明移动到类定义之前才能解决您的问题:

struct CAT
{
    std::string name;
    CAT(){std::cout<<"CAT"<<std::endl;}
    ~CAT(){std::cout<<"~CAT"<<std::endl;}
};

class Widget {
    public:
        Widget();
        ~Widget() {
            delete pc; // I kNow we should put this code to cpp
                       // I am just want to show the difference behavior
                       // between raw pointer and smart pointer
                       // when widget object destruct
        }
    private:
        struct Impl;
        std::shared_ptr<Impl> pImpl;  // use smart pointer
        CAT *pc;  //raw pointer
};

输出

Impl
CAT
~CAT
~Impl

转发声明有助于加快编译时间,但是当需要有关数据类型的更多信息时可能会导致问题.

但为什么它可以用于智能指针?
这是一个更好的解释:Deletion of pointer to incomplete type and smart pointers

基本上,在初始化或重置指针时,shared_ptr只需要声明.这意味着在声明的时刻不需要完整的类型.

大佬总结

以上是大佬教程为你收集整理的c – 为什么不完整类型的智能指针数据成员和原始指针数据成员在其父级破坏时具有不同的行为?全部内容,希望文章能够帮你解决c – 为什么不完整类型的智能指针数据成员和原始指针数据成员在其父级破坏时具有不同的行为?所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。