Ang*_*ber 9 c++ pointers c++11
这是使用std智能指针确保ptr安全的正确方法
这个例子可能不是最好的,但我试图模仿一些真正的代码.我遇到的问题是在实际代码中,通信器指针是一个原始指针,可以在任何时刻解除分配 - 导致使用指针崩溃.
所以我决定查看std :: shared_ptr和std :: weak_ptr以了解它应该如何设计现在我们有C++ 11.我在发送代码中使用weak_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!");
}
Run Code Online (Sandbox Code Playgroud)
输出:
sending Hi guys! using myname at 9600 rate and using com port 3
Attempting to send: Hi guys after ptr delete! but ptr no longer exists
Run Code Online (Sandbox Code Playgroud)
可以随时取消分配的指针 - 导致使用指针时崩溃
这就是引入 ; 的理由背后的症状weak_ptr。因此我认为你weak_ptr基于 - 的方法是正确的。
然而,我发现有争议的是,与此相结合
sender() : comms_() {}
void set_communicator(std::weak_ptr<communicator> comms) {
comms_ = comms;
}
Run Code Online (Sandbox Code Playgroud)
sender内部资产的两阶段构建comms_
一旦 lock() 失败,您不会将内部资产的状态重置为构建后状态
void send(const std::string& s)
Run Code Online (Sandbox Code Playgroud)
但这本身并不是“错误”。这只是可以考虑用于完整应用程序的东西。
另一件事是,当失败时你不会throw(或者让ctor (#11)抛出shared_ptr(weak_ptr))lock(),而只是if-else 处理它。我无法知道您的完整应用程序的要求,但根据您组装的摘录,基于异常的错误处理将改进设计。
例如:
#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;
}
Run Code Online (Sandbox Code Playgroud)
住在 Coliru 的
| 归档时间: |
|
| 查看次数: |
298 次 |
| 最近记录: |