假设我有这样的东西:
class A
{
public:
A(int x, int y)
{
std::cout << "Constructed from parameters" << std::endl;
}
// Non-copyable, non-movable
A(A const&) = delete;
A(A&&) = delete;
A& operator=(A const&) = delete;
A& operator=(A&&) = delete;
};
class B
{
public:
B() = default;
private:
A a{1,2};
};
int main()
{
B b;
return 0;
}
这工作正常,通过调用 A
的构造函数用默认值初始化 a
,并打印 Constructed from parameters
。
然后,假设我想以不同的方式初始化 a
,因此我添加了一个采用初始化列表的构造函数并更改了我的代码:
class A
{
public:
A(int x, int y)
{
std::cout << "Constructed from parameters" << std::endl;
}
A(std::initializer_list<int> someList)
{
std::cout << "Constructed from an initializer list" << std::endl;
}
// Non-copyable, non-movable
A(A const&) = delete;
A(A&&) = delete;
A& operator=(A const&) = delete;
A& operator=(A&&) = delete;
};
class B
{
public:
B() = default;
private:
A a{1,2,3};
};
int main()
{
B b;
return 0;
}
一切仍然如我所愿,代码通过调用 A
的第二个构造函数用默认值初始化 a
并打印 Constructed from an initializer list
.
现在,假设我想保持 A
不变,但返回到通过第一个构造函数设置 a
的默认值。如果 A
是可移动的,我可以使用 A a = A(1,2);
,但这里不是这种情况,那么我该怎么做呢?使用该构造函数设置默认值显然是不可能的吗?
编辑:我正在寻找适用于 C++14 的解决方案,但如果在 C++17 或 C++20 中有更好的解决方案,那也是我想知道的。
最佳答案
If A was movable, I could use
A a = A(1,2);
, but that isn't the case here
好吧,对于 C++17 及更高版本,您可以在这里使用 A a = A(1,2);
,只要您将它作为声明/初始化!以下作品(在您的第二个代码片段中):
class B {
public:
B() = default;
private:
A a = A( 1, 2 ); // No assignment here - just an initialization.
};
和“从参数构造”被调用。这是因为这里没有实际的赋值操作,只是一个初始化。但是,由于您所说的原因,以下操作将失败:
class B {
public:
B() { a = A( 1, 2 ); } // error C2280: 'A &A::operator =(A &&)': attempting to reference a deleted function
private:
A a{ 1,2,3 };
};
编辑:C++17 之前的版本,以下是一种解决方法,在 B
的默认构造函数的初始化列表中使用“老式”圆括号,而不是大括号(在 clang-cl 和 MSVC 中使用 C++14 测试):
class B {
public:
B() : a(1,2) {} // Using a{1,2} calls the "initializer list" constructor, however!
private:
A a;
};
关于c++ - 如何使用初始化列表构造函数以外的东西为类成员设置默认值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64481212/