C++ 正确使用std智能指针以确保ptr安全

C++ 正确使用std智能指针以确保ptr安全,c++,pointers,c++11,C++,Pointers,C++11,这是使用std智能指针确保ptr安全的正确方法吗 这个例子可能不是最好的,但我试图模拟一些真实的代码。我遇到的问题是在实际代码中,通信器指针是一个原始指针,可以在任何时候取消分配-导致使用指针时崩溃 所以我决定研究一下std::shared\u ptr和std::weak\u ptr,看看现在我们有了C++11,应该如何设计它。我在发送代码中使用了一个弱ptr,它检查ptr是否仍然有效,然后才会取消对ptr的引用。这个代码是正确的方法吗?有什么改进吗 #include <memory>

这是使用std智能指针确保ptr安全的正确方法吗

这个例子可能不是最好的,但我试图模拟一些真实的代码。我遇到的问题是在实际代码中,通信器指针是一个原始指针,可以在任何时候取消分配-导致使用指针时崩溃

所以我决定研究一下std::shared\u ptr和std::weak\u ptr,看看现在我们有了C++11,应该如何设计它。我在发送代码中使用了一个弱ptr,它检查ptr是否仍然有效,然后才会取消对ptr的引用。这个代码是正确的方法吗?有什么改进吗

#include <memory>
#include <iostream>
#include <string>

class communicator
{
public:
    communicator(const char* name, int comport, int speed) : name_(name), comport_(comport), speed_(speed) { }

    void send(const std::string& s) {
        std::cout << "sending " << s << " using " << name_ << " at " << speed_ << " rate and using com port " << comport_ << '\n';
    }

private:
    const char* name_;
    int comport_;
    int speed_;
};

class sender
{
public:
    sender() {}

    void set_communicator(std::weak_ptr<communicator> comms) {
        comms_ = comms;
    }

    void send(const std::string& s)
    {
        if (auto sh = comms_.lock())
            sh->send(s);
        else
            std::cout << "Attempting to send: " << s << " but ptr no longer exists\n";
    }

private:
    std::weak_ptr<communicator> comms_;
};

int main() {

    sender mysender;

    {
        // create comms object
        std::shared_ptr<communicator> comms(new communicator("myname", 3, 9600));

        mysender.set_communicator(comms);

        mysender.send("Hi guys!");

    }  // comms object gets deleted here

    mysender.send("Hi guys after ptr delete!");
}
可以随时取消分配的指针-导致 在使用指针时崩溃

这就是引入
弱ptr
的理由背后的症状;因此,我将考虑您的<代码>弱pPTR <代码>为基础的方法。< /p> 然而,我认为有争议的是,与此相关的是

sender() : comms_() {}

void set_communicator(std::weak_ptr<communicator> comms) {
    comms_ = comms;
}
但这本身并不是“错误的”;这只是一些可以考虑的全面应用程序

另一件事是,当
lock()
失败时,您不会
抛出
(或),而只是
if-else
处理它。我不知道您的全尺寸应用程序的要求,但基于您组装的摘录,基于异常的错误处理将改进设计

例如:

#包括
#包括
#包括
#包括
类通信器
{
公众:
通信器(常量字符*名称、整数成分、整数速度)
:name_(name)、comport_(comport)、speed_(speed){
void send(const std::string&s){
标准::cout
这是使用std智能指针确保ptr安全的正确方法吗

除了decltype_auto提到的内容外,我可以补充一点,使用弱_ptr的原因之一是为了防止循环依赖。如果不存在这种可能性,您还可以将其共享,这将使发送的实现不太容易出错,除非通信通道的生存期是真是暂时的


您可以隐藏在实现中存在各种连接或会话的事实。

< P>也可以在使用标准智能指针设计接口/ API时,考虑使用更为受限的指针,如UNQuijyPosik.</P>。
这样的指针可以非常清楚地传达意图——例如,通过将唯一指针作为函数的参数,您可以清楚地告诉用户,他正在将指向的资源的所有权移交给被调用的函数。

可能更适合codereview。我会使用
std::make_shared
sender() : comms_() {}

void set_communicator(std::weak_ptr<communicator> comms) {
    comms_ = comms;
}
void send(const std::string& s)
#include <memory>
#include <stdexcept>
#include <iostream>
#include <string>

class communicator
{
public:
    communicator(const char* name, int comport, int speed) 
        : name_(name), comport_(comport), speed_(speed) { }

    void send(const std::string& s) {
        std::cout << "sending " << s << " using " << name_ << " at " 
                  << speed_ << " rate and using com port " << comport_ 
                  << '\n';
    }

private:
    const char* name_;
    int comport_;
    int speed_;
};

class sender
{
public:
    struct invalid_communicator : public std::runtime_error {
        invalid_communicator(const std::string& s) :
            std::runtime_error(
                std::string("Attempting to send: \"") + s 
                    + "\" but communicator is invalid or not set"
            ) {}
    };  

    sender() : comms_() {}

    void set_communicator(std::weak_ptr<communicator> comms) {
        comms_ = comms;
    }

    /* non-const */
    void send(const std::string& s) throw (invalid_communicator)
    {
        try {
            auto sh = std::shared_ptr<communicator>(comms_);
            sh->send(s);
        } catch (const std::bad_weak_ptr& e) {
            comms_ = decltype(comms_)();
            throw invalid_communicator(s);
        }
    }

private:
    std::weak_ptr<communicator> comms_;
};

int main() {
    int rv = -1;
    sender mysender;

    for (auto com : {1, 2, 3}) {
        try {
            { 
                // create comms object
                auto comms = std::make_shared<communicator>(
                    "myname", com, 9600
                );
                mysender.set_communicator(comms);
                mysender.send("Hi guys!");
            }// comms object gets deleted here

            mysender.send("Hi guys after ptr delete!"); 

            // never reached in this example; just to illustrate
            // how the story could continue  
            rv = EXIT_SUCCESS;            
            break; // it'd be not nice to "break", but I did not want to
                   // introduce another state variable
        } catch (const sender::invalid_communicator& e) {
            std::cerr << e.what() << std::endl;
        }
    }

    return rv;
}