首页 > 解决方案 > C++如何通过“构造函数初始化”来初始化内联变量?

问题描述

我正在做我的教授在上次考试中给我的一个练习。

正文如下(译文,原文为意大利语):

编写一个SmartP<T>智能指针类型的类模板T,重新定义智能指针的赋值、复制构造函数和析构函数。模板SmartP<T>必须包含允许编译以下代码的最小公共接口(具有较少数量的成员),执行将引发注释行

class C {
public:
    int* p;
    C(): p(new int(5)) {}
};

int main() {
    const int a = 1;
    const int *p = &a;
    SmartP<int> r;
    SmartP<int> s(&a);
    SmartP<int> t(s);
    cout << *s << " " << *t << " " << *p << endl; // 1 1 1
    cout << (s == t) << " " << !(s == p) << endl; // 0 1
    *s = 2;
    *t = 3;
    cout << *s << " " << *t << " " << *p << endl; // 2 3 1
    r = t;
    *r = 4;
    cout << *r << " " << *s << " " << *t << " " << *p << endl; // 4 2 3 1
    C c;
    SmartP<C> x(&c);
    SmartP<C> y(x);
    cout << (x == y) << endl; // 0
    cout << *(c.p) << endl; // 5
    *(c.p) = 6;
    cout << *(c.p) << endl; // 6
    SmartP<C> *q = new SmartP<C>(&c);
    delete q;
}

我的教授提供的解决方案如下:

template<class T>
class SmartP{
private:
    T* ptr;
public:
    SmartP(const SmartP& p) { p.ptr!=0 ? ptr(new T(*(p.ptr))) : ptr(nullptr); };
    SmartP(const T* t = 0) { t!=0 ? ptr(new T(*t)) : ptr(nullptr); };
    ~SmartP() { delete ptr;}
    T& operator*() const { return *ptr;}
    bool operator==(const SmartP& p) const { return ptr == p.ptr;}
    SmartP& operator=(const SmartP& p) {
       delete ptr;
       p.ptr!=0 ? ptr(new T(*(p.ptr))) : ptr(nullptr);
       return *this;
    }
};

但是当我尝试这个时,每个“构造函数初始化”都会出错,上面写着:

调用的对象类型'C*'不是函数或函数指针”(请注意,如果我删除 C 类,我会得到相同的错误,但在 'C*' 上却有 'int*')。

所以我对此很感兴趣,我给它一些测试:

    SmartP(const SmartP& p) : ptr(new T(*(p.ptr))) {}; //no error
    SmartP(const SmartP& p) { ptr(new T(*(p.ptr))); }; //error
    SmartP(const SmartP& p) { ptr = new T(*(p.ptr)); }; //no error
    SmartP(const SmartP& p) {
        if(p.ptr!=0){
            ptr(new T(*(p.ptr))); //error
        } else {
            ptr(nullptr);
        }
    };

所以我的问题是 C++ 如何通过“构造函数初始化”初始化内联变量?

为什么如果我正常初始化我的变量它可以工作,但不能使用“构造函数初始化”?

标签: c++constructorinitialization

解决方案


ptr(new T(*(p.ptr)));这种成员初始化只允许在其主体之外的构造函数中,也就是成员初始化列表。ptr如果您在构造函数主体中使用此行,则它是对具有名称或的函数的调用ptr.operator()。编译器说你完全一样,ptr类型C*不是函数也不是函数对象。

只有两种初始化方式ptr是可能的,所有这些方式都在你的第一行和第三行,你标记为没有错误。

更多信息:构造函数和成员初始化器列表


推荐阅读