提问人:Ya Ihniy 提问时间:6/18/2023 最后编辑:Peter MortensenYa Ihniy 更新时间:6/18/2023 访问量:150
Clang 错误:调用私有构造函数,而实际上没有调用它们
Clang error: calling a private constructor while none of them were actually called
问:
我做了一个类的静态函数,并将构造函数设为私有。现在我想使用这个函数。Clang++ 说“构造函数是私有的”,而 g++ 可以正常编译。
我不知道任何标准中是否有任何规则可能会以任何方式影响这一点。任何函数都可以生成一个变量,并且没有变量,并且无法返回值。所以上面的代码中应该没有任何错误,对吧?但 Clang 对此有不同的看法。MyStruct::make
这是 Clang 应该做到的,还是永远不应该在 C++ 中做的事情?
我试图让 C++ 在这里更像 Rust,这样我就永远不会对构造函数做一些意想不到的事情。我使用了 g+,以下代码有效。
#include <iostream>
#include <optional>
#include <utility>
class MyStruct {
public:
static auto make(int val) -> MyStruct {
MyStruct that(val);
return that;
};
auto copy() -> MyStruct {
MyStruct copy(this->val);
return copy;
}
auto value() -> int { return this->val; }
private:
MyStruct() = delete;
MyStruct(int val) { this->val = val; }
MyStruct(const MyStruct &other) { this->val = other.val; }
int val;
};
auto main() -> int {
auto my_struct = MyStruct::make(4);
auto my_new_struct = my_struct.copy();
std::cout << my_new_struct.value();
std::cout << MyStruct::make(7).value();
}
但是,使用 Clang 时,我遇到了一些错误:
main.cpp:30:20: error: calling a private constructor of class 'MyStruct'
auto my_struct = MyStruct::make(4);
^
main.cpp:24:3: note: declared private here
MyStruct(const MyStruct &other) { this->val = other.val; }
^
main.cpp:32:24: error: calling a private constructor of class 'MyStruct'
auto my_new_struct = my_struct.copy();
^
main.cpp:24:3: note: declared private here
MyStruct(const MyStruct &other) { this->val = other.val; }
^
2 errors generated.
换句话说,这是 Clang 应该做到的,还是永远不应该在 C++ 中做的事情,为什么?
答:
0赞
cse
6/18/2023
#1
这取决于您的编译器版本和编译器标志。
对于 Clang 版本 5.0.1,代码使用 C++17(编译器开关 -std=c++17)进行编译,但不在 C++11(编译器开关 -std=c
++11
)上编译。
请参阅此处的代码是使用 set 编译的。但是如果我们将 .-std=c++17
-std=c++11
1赞
Vlad from Moscow
6/18/2023
#2
形式上,例如在这一行中
auto my_struct = MyStruct::make(4);
如果不考虑复制/移动省略,则应使用复制结构器。
在 C++ 17 标准之前,复制构造函数应该是可以接受的,即使它的调用被省略了。
来自 C++ 14 标准( 12.8 复制和移动类对象)
- ...[注意:无论是否会发生复制省略,都必须执行此两阶段过载解决。它决定了 未执行省略时调用的构造函数,以及 即使省略了调用,选定的构造函数也必须可访问。 — 结束语 ]
要么公开复制构造函数,要么打开至少对 C++ 17 标准的支持。
评论
0赞
Ya Ihniy
6/18/2023
这真是太神奇了。这很有道理,但非常令人惊讶。奇怪的是,我没有想到移动语义之前不在 C++ 中。谢谢。
0赞
Vlad from Moscow
6/18/2023
@YaIhniy完全没有。不客气:)
评论