代码之家  ›  专栏  ›  技术社区  ›  fredoverflow

变量构造函数是否应该隐藏隐式生成的构造函数?

  •  27
  • fredoverflow  · 技术社区  · 15 年前

    变量构造函数是否应该隐藏隐式生成的构造函数,即默认构造函数和复制构造函数?

    struct Foo
    {
        template<typename... Args> Foo(Args&&... x)
        {
            std::cout << "inside the variadic constructor\n";
        }
    };
    
    int main()
    {
        Foo a;
        Foo b(a);
    }
    

    不知怎的,我希望这本书读完后什么也不印。 this answer 但是它打印出来了 inside the variadic constructor 在G++4.5.0上两次:(这种行为正确吗?


    在没有可变模板的情况下也会发生这种情况:

    struct Foo
    {
        Foo()
        {
            std::cout << "inside the nullary constructor\n";
        }
    
        template<typename A> Foo(A&& x)
        {
            std::cout << "inside the unary constructor\n";
        }
    };
    
    int main()
    {
        Foo a;
        Foo b(a);
    }
    

    同样,两行都被打印出来。

    1 回复  |  直到 13 年前
        1
  •  21
  •   James McNellis    15 年前

    实际上,隐式声明的复制构造函数的声明不会被禁止。这只是因为过载解决规则而没有被调用。

    隐式声明的复制构造函数具有以下形式 Foo(const Foo&) . 其中重要的一点是它需要一个常量引用。构造函数模板采用非常量引用。

    a 不是const,因此非const用户声明的构造函数模板优先于隐式声明的复制构造函数。要调用隐式声明的复制构造函数,可以 康斯特:

    const Foo a;
    Foo b(a);
    

    或者你可以使用 static_cast 获取常量引用 :

    Foo a;
    Foo b(static_cast<const Foo&>(a));
    

    描述这一点的过载解决规则主要是在C++ 0xFCD的{3.3.3.2/3中找到的。这个特殊的场景结合了lvalue和rvalue引用,有点像第303页上的各种示例所描述的那样。


    变量构造函数模板将抑制隐式声明的默认构造函数,因为用户声明了一个可变构造函数模板,如果没有用户声明的构造函数(C++0x FCD×12.1),则只提供隐式声明的默认构造函数:

    如果没有用户声明的类构造函数 X ,没有参数的构造函数被隐式声明为默认的。

    变量构造函数模板不会抑制隐式声明的复制构造函数,因为只有非模板构造函数可以是复制构造函数(C++0x FCD-Syth.128/2,3和8):

    类的非模板构造函数 X 如果其第一个参数的类型为 X& , const X& , volatile X& const volatile X& ,或者没有其他参数,或者所有其他参数都有默认参数。

    类的非模板构造函数 X 如果其第一个参数的类型为 X&& , const X&& , volatile X&& const volatile X&& ,或者没有其他参数,或者所有其他参数都有默认参数。

    如果类定义没有显式声明复制构造函数,并且没有用户声明的移动构造函数,则复制构造函数将隐式声明为默认值。

    推荐文章