默认参数和空列表初始化

Default argument and empty list initialization

考虑以下代码,一个简单的 class 构造函数采用默认值作为参数。

// Version 1
template <class T>
struct object1 {
    using type = T;
    constexpr object1(const type& val = type()): value(val) {}
    type value;
};

// Version 2
template <class T>
struct object2 {
    using type = T;
    constexpr object2(const type& val = {}): value(val) {}
    type value;
};

// Main
int main(int argc, char* argv[]) {
    using type = /* Something */;
    object1<type> x1;
    object2<type> x2;
    auto value1 = x1.value;
    auto value2 = x2.value;
    // Is there certain types for which value1 and value2 will be different?
    return 0;
}

构造函数的两个版本是等效的(对任何 T 总是产生相同的结果),还是不同?

如果它们不同,您能否提供一个 T 两者会导致不同结果的示例?

不,它们不等同。第二个变体依赖于 T 的默认构造函数的隐式:

class foo
{
   public: explicit foo() {}
};

object1<foo> of{}; // ok
object2<foo> of{}; // error

另外我认为从临时调用复制构造函数而不是调用没有临时构造函数的默认构造函数不是一个好主意。那就是实现单独的构造函数会更好:

template <class T>
struct object1 {
    using type = T;
    constexpr object1(void): value{} {}

    constexpr object1(const type& val): value{val} {}

    type value;
};