- android - RelativeLayout 背景可绘制重叠内容
- android - 如何链接 cpufeatures lib 以获取 native android 库?
- java - OnItemClickListener 不起作用,但 OnLongItemClickListener 在自定义 ListView 中起作用
- java - Android 文件转字符串
在下面的例子中,gcc 7 给出了警告:
defaulted move assignment for 'B' calls a non-trivial move assignment operator for virtual base 'A' [-Wvirtual-move-assign]
如果我创建一个 std::tuple<B>
目的。 Clang 5 没有报告任何问题。如果vector
,问题也会消失从 Base
中删除. Example .
#include <tuple>
#include <vector>
class Base
{
public:
virtual ~Base();
std::vector<int> v;
};
class A : public Base
{
};
class B : public virtual A
{
};
int main()
{
B *b = new B;
B another{*b}; // <<<--- this compiles
std::tuple<B> t; // <<<--- gives warning
}
为什么会在 std::tuple
存在的情况下发生? (并且没有移动分配)如果我需要保持这样的层次结构,修复它的正确方法是什么?
最佳答案
警告与元组
无关,它是由B
的移动赋值触发的。例如,以下代码生成警告
B b;
B t;
t = std::move(b);
gcc documentation解释警告的意图
-Wno-virtual-move-assign
Suppress warnings about inheriting from a virtual base with a non-trivial C++11 move assignment operator. This is dangerous because if the virtual base is reachable along more than one path, it is moved multiple times, which can mean both objects end up in the moved-from state. If the move assignment operator is written to avoid moving from a moved-from object, this warning can be disabled.
这是一个 example说明问题
struct Base
{
Base() = default;
Base& operator=(Base&&)
{
std::cout << __PRETTY_FUNCTION__ << '\n';
return *this;
}
};
struct A : virtual Base {};
struct B : virtual Base {};
struct C : A, B {};
int main()
{
C c;
c = C();
}
这会产生输出
Base& Base::operator=(Base&&)
Base& Base::operator=(Base&&)
显示单个 Base
实例被移动赋值了两次,一次是通过 A
和 B
的每个移动赋值运算符。第二个移动分配来自一个已经移动的对象,这可能会导致第一个移动分配的内容被覆盖。
请注意,在我的示例中,clang 也会生成警告,它可能检测到 A
在您的示例中无法通过两条路径访问,因此不会发出警告。
修复它的方法是为 A
和 B
实现移动赋值运算符,它可以检测到 Base
已被移动并省略第二次移动任务。
关于c++ - 为什么 gcc 警告使用 std::tuple 和虚拟继承调用非平凡的移动赋值运算符?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46599222/
我是一名优秀的程序员,十分优秀!