问题 将指向数据成员的指针传递给基类构造函数是否安全?


将指向数据成员的指针传递给基类构造函数是否安全?即,即使数据成员尚未初始化,至少已经在调用基类构造函数之前设置了派生类数据成员的内存布局?

显然,只有在构造完成后才能取消引用指针,并且指向的对象已经有效。但问题是,如果确保派生对象的构造完成后,基类构造函数接收的指针实际上仍然指向它们的对象。

动机是在基类中提供一些功能,例如迭代构造时提供的指针到对象,并在以后为每个执行某些操作。

可以只提供派生类可访问的setter,但我很好奇是否在构造时提供指针也是安全的。

例:

#include <iostream>
#include <utility>
#include <vector>

struct Base {
   Base(std::initializer_list<int*> ptrs = {}) : ptrs_(ptrs) {}
   std::vector<int*> ptrs_;
};

struct Derived : public Base {
    Derived() : Base{{&a_,&b_,&c_}} {}
    int a_=1, b_=2, c_=3;
};

int main()
{
    Derived obj;
    for (auto* ptr : obj.ptrs_) { std::cout << *ptr << '\n'; }
}

https://wandbox.org/permlink/rDJw0UU8KcWckLlo


4338
2018-04-10 15:24


起源

注意:请使用括号进行初始化 ptrs_。这是一个非常尖锐的优势 {} 初始化具有的类型 initializer_list 当您没有专门使用该功能时,构造函数。 - Barry
@Barry做完了,谢谢! - Danra


答案:


你的代码很好。 但请注意行为 提领 基类构造函数中的指针将是未定义的。

你被允许通过 指针 要么 参考 到成员变量到基类构造函数,但您不能实际访问该基类构造函数中的对象。


10
2018-04-10 15:27



好吧,我仍然有第一个版本在我的脑海里,我想编辑的答案很好:) - user463035818
我在这个问题上添加了一个更明确的澄清段落。 - Danra
任何相关的标准参考? - Danra
@Danra - 只要你保证只有在成员初始化之后指针被解除引用,你才会被设置。在对象之前“欺骗”并获取对象的引用并不罕见 那里。这是标准参考,使它成为犹太洁食: eel.is/c++draft/basic.life#6 - StoryTeller
我全都被限制了:)除此之外,你说我的咖啡被剥夺了大脑的能力,现在更好了;) - StoryTeller