- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我开发了一些可以正确编译但在(调试)运行时失败的代码。我正在使用 VS2015。
背景:我正在构建一个高级消息引擎。为了使新消息的编程添加可维护,在生产代码中,我花时间使用 explicit initialization declaration
C++ 构造来制作初始消息。这行得通并使新消息的制作变得千篇一律,更不用说将消息传递的维护工作减少到几乎为零。这是此功能的框架代码:
#include <memory>
template< typename D_T >
struct H // prototype for all explicit initialization declarations (EID)
{
H( D_T& d ) : x { d } {}
D_T& x;
};
template< typename D_T >
struct B // base class for derived objects D1 and D2
{
B( D_T& d ) : d { d } {}
D_T& d; // a kind of backptr initialized when the EIDs are contructed
// actual EIDs a and b
H< D_T > a { d };
H< D_T > b { d };
};
struct D1 : public B< D1 >
{
D1() : B( *this ) {}
void Func1() {}
};
struct D2 : public B< D2 >
{
D2() : B( *this ) {}
void Func2() {}
};
int main()
{
D1 d1;
D2 d2;
// as designed either derived object can access either explicitly initialized member a or b
d1.a.x.Func1(); // OK
d1.b.x.Func1(); // OK
d2.a.x.Func2(); // OK
d2.b.x.Func2(); // OK
return 0;
}
此代码编译并运行。
但是我在真实代码中的派生对象是共享指针。因此,我将此功能添加到代码中。请注意,我正在使用 enable_shared_from_this
构造获取派生类的 this
ptr:
#include <memory>
template< typename D_T >
struct H
{
H( std::shared_ptr< D_T >& d ) : x { d } {}
std::shared_ptr< D_T >& x;
};
template< typename D_T >
struct B
{
B( std::shared_ptr< D_T >& d ) : d { d } {}
std::shared_ptr< D_T >& d;
H< D_T > a { d }; // a is initialized with D1
H< D_T > b { d };
};
struct D1: public std::enable_shared_from_this< D1 >, public B< D1 >
{
D1() : B( shared_from_this() ) {} // runtime error: bad weak prt
void Func1() {}
};
struct D2: public std::enable_shared_from_this< D2 >, public B< D2 >
{
D2() : B( shared_from_this() ) {}
void Func2() {}
};
int main()
{
D1 d1;
D2 d2;
d1.a.x->Func1();
d1.b.x->Func1();
d2.a.x->Func2();
d2.b.x->Func2();
return 0;
}
此代码编译。但是,它不会运行,并且在 D1 构造函数中,它会因 std::bad_weak_ptr 异常而中断。
我曾尝试将 shared ptrs 更改为 weak ptrs 但没有成功。有人看到问题了吗?
编辑 1:根据 @pat 的观察,shared_from_this()
不能从构造函数调用,请参阅下面修改后的代码,现在可以编译和运行:
#include <memory>
template< typename D_T >
struct H
{
H( D_T& d ) : x { d } {}
D_T& x;
};
template< typename D_T >
struct B
{
B( D_T& d ) : d { d } {}
D_T& d;
H< D_T > a { d };
H< D_T > b { d };
};
struct D1 : public std::enable_shared_from_this< D1 >, public B< D1 >
{
D1() : B( *this ) {}
void Func1() {}
};
struct D2 : public std::enable_shared_from_this< D1 >, public B< D2 >
{
D2() : B( *this ) {}
void Func2() {}
};
int main()
{
D1 d1;
D2 d2;
d1.a.x.Func1();
d1.b.x.Func1();
d2.a.x.Func2();
d2.b.x.Func2();
return 0;
}
编辑 2:下面的代码是对我原来的帖子代码的重写,并建立在@pat 的回答之上。以下是更改内容:显式实例化声明 (EID) 已移至其派生类。 B 不再尝试引用派生对象。这是一个明显的错误。作为后向指针的 weak_ptr 被一个简单的后向指针所取代(就像原型(prototype)中的情况一样)。没有泄漏问题,因为派生对象(D1 和 D2)完全拥有该对象。 (在生产代码中,成员类型是共享指针以防止泄漏。)
#include <memory>
#include <cassert>
template< typename D_T >
struct H
{
H( D_T* d ) : x { d } {}
D_T* x;
int qq { 0 };
};
struct B
{
B() {}
int rr { 0 };
};
struct D1 : public B
{
H< D1 > a { this }; // explicit instantiation declaration
int ss { 0 };
};
struct D2 : public B
{
H< D2 > b { this }; // explicit instantiation declaration
int tt { 0 };
};
int main()
{
D1 d1;
D2 d2;
d1.rr = 99;
d2.b.x->rr = 88;
assert( d1.rr == d1.a.x->rr ); // OK
assert( d2.rr == d2.b.x->rr ); // OK
return 0;
}
当添加任意数量的 EID 时,代码维护复杂性从指数(如原型(prototype)中的情况)降低到线性的设计不变性已经实现。
最佳答案
对象必须由共享指针管理,shared_from_this
才能工作。在尚未由 shared_ptr
管理的对象上调用 shared_from_this
实际上是 C++14 中的未定义行为。因此,您将无法从构造函数调用 shared_from_this
,因为此时该对象不在 shared_ptr
中。
来自 cppreference 的示例...
struct Good: std::enable_shared_from_this<Good>
{
std::shared_ptr<Good> getptr() {
return shared_from_this();
}
};
// Bad: shared_from_this is called without having std::shared_ptr owning the caller
try {
Good not_so_good;
std::shared_ptr<Good> gp1 = not_so_good.getptr();
} catch(std::bad_weak_ptr& e) {
// undefined behavior (until C++17) and std::bad_weak_ptr thrown (since C++17)
std::cout << e.what() << '\n';
}
关于c++ - 使用显式实例化声明删除反向指针会导致 std::bad_weak_ptr 异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40660935/
我正在开发一个小型图书馆,我需要做的一件事是让访问者访问一些数据并返回结果。 在一些较旧的 C++ 代码中,访问者需要声明一个 typedef return_type .例如,boost::stati
我正在尝试使用std:map类型的键和值制作std::any Visual Studio 2017 std::map m("lastname", "Ivanov"); std::cout (m["la
我已经在 C++ 的 map 中声明了一个集合为 std::map> .如何循环访问或打印设定值? 最佳答案 如果你知道如何迭代 std::map或 std::set单独地,您应该可以毫无问题地组合迭
如何循环? 我已经试过了: //----- code std::vector >::iterator it; for ( it = users.begin(); it != users.end();
我有两个用例。 A.我想同步访问两个线程的队列。 B.我想同步两个线程对队列的访问并使用条件变量,因为其中一个线程将等待另一个线程将内容存储到队列中。 对于用例 A,我看到了使用 std::lock_
我正在查看这两种类型特征的文档,但不确定有什么区别。我不是语言律师,但据我所知,它们都适用于“memcpy-able”类型。 它们可以互换使用吗? 最佳答案 不,这些术语不能互换使用。这两个术语都表示
我有以下测试代码,其中有一个参数 fS,它是 ofstream 的容器: #include #include #include #include int
这是这个问题的延续 c++ function ptr in unorderer_map, compile time error 我试图使用 std::function 而不是函数指针,并且只有当函数是
std::unordered_map str_bool_map = { {"a", true}, {"b", false}, {"c", true} }; 我们可以在此映射上使
我有以下对象 std::vector> vectorList; 然后我添加到这个使用 std::vector vec_tmp; vec_tmp.push_back(strDRG); vec_tmp.p
为什么 std::initializer_list不支持std::get<> , std::tuple_size和 std::tuple_element ?在constexpr中用得很多现在的表达式,
我有一个像这样定义的变量 auto drum = std::make_tuple ( std::make_tuple ( 0.3f , Ex
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
假设我有一个私有(private)std::map在我的类(class)里std::map 。我怎样才能将其转换为std::map返回给用户?我想要下面的原型(prototype) const std
问题 我正在尝试将 lambda 闭包传递给 std::thread,它使用任意封闭参数调用任意封闭函数。 template std::thread timed_thread(Function&& f
我想创建一个模板类,可以容纳容器和容器的任意组合。例如,std::vector或 std::map ,例如。 我尝试了很多组合,但我必须承认模板的复杂性让我不知所措。我编译的关闭是这样的: templ
我有一个 std::vector>我将其分配给相同类型的第二个 vector 。 我收到这个编译器错误: /opt/gcc-8.2.0/include/c++/8.2.0/bits/stl_algob
有时候,我们有一个工厂可以生成一个 std::unique_ptr vector ,后来我们想在类/线程/你命名的之间共享这些指针。因此,最好改用 std::shared_ptr 。当然有一种方法可以
这个问题在这里已经有了答案: Sorting a vector of custom objects (14 个答案) 关闭 6 年前。 我创建了一个 vector vector ,我想根据我定义的参
我有三个类(class)成员: public: std::vector > getObjects(); std::vector > getObjects() const; privat
我是一名优秀的程序员,十分优秀!