我正在尝试(不成功地)创建一个对象向量并使用polimophism而不需要手动内存管理和依赖raii习惯用法的任何类型的指针(*,unique_ptr,shared_ptr,weak_ptr等)。
#include <iostream>
#include <vector>
using namespace std;
struct A{
virtual void foo()=0;
virtual ~A(){}
};
struct C:A{
int bar;
C(int bar):bar(bar){}
virtual void foo(){
cout << bar << endl;
}
virtual ~C(){}
};
struct B:A{
vector<A> &&bar;
int f;
B(int f, vector<A> bar):f(f),bar(bar){}
B(int f, vector<A> &bar):f(f),bar(bar){}
B(int f, vector<A> &&bar):f(f), bar(bar){}
virtual void foo(){
cout << f << endl;
for(auto &f: bar){
f.foo();
}
}
virtual ~B(){}
};
int main() {
B b{1, vector<A>{C{1},C{2}}};
b.foo();
return 0;
}
但它没有编译。我做错了什么?
答案 0 :(得分:2)
std::vector<A> something
是一个向量,在添加对象时为A
和A
动态分配存储空间。
向量的存储类型为A
,它存储A
的实例。
当您将第一个C
推到它上面时,它会执行以下操作:
void push_back(const A& a) // NOTE: A, not C, downcasting occurs
{
// extreme aproximation
if (something.begin_ == nullptr) {
something.begin_ = new A;
something.begin_[0] = a; // A::operator=(const A&);
something.capacity_ = something.end_ = something.begin_ + 1;
} else {
..
}
}
由于C
继承自A
,因此可以向下转发。但是,它只会复制传递给它的对象的A
部分,因为向量的存储类型是A
,因此您的int bar
C
中未复制。
这称为切片,它的唯一方法是动态(指针或std :: any),或使用联合的危险路径。
- 编辑 -
您希望std::vector<A> &&bar
做的第二个问题是什么?它引用的临时对象在构造函数表达式的末尾到期:
B b{1, vector<A>{C{1},C{2}}}; // temporary vector is destroyed
// b.bar is dangling rvalue reference
- 编辑2 -
您的问题标题包含&#34;使用移动语义&#34;但如编辑1中所述,您只存储右值参考。移动语义是关于转移的:考虑这个简单的strdup
包装器:
struct Strdupper {
char* str_;
Strdupper() = delete;
Strdupper(const char* str) : str_(strdup(str)) {}
~Strdupper() { if (str_) free(str_); }
Strdupper(const Strdupper& rhs) { str_ = strdup(rhs.str_); }
Strdupper(Strdupper&& rhs) str_(rhs.str_) { rhs.str_ = nullptr; }
Strdupper& operator=(const Strdupper& rhs) { if (str_) free(str_); str_ = strdup(rhs.str_); return *this; }
Strdupper& operator=(Strdupper&& rhs) { std::swap(str_, rhs.str_); return *this; }
// ...
};
而不是rvalue引用,你的类B需要实际存储向量并将std::move
输入参数值存储到其构造函数中以调用它的move-constructor:
class B {
std::vector<X> vec_;
public:
B() = default;
B(const std::vector<X>& vec) : vec_(vec) {} // copy semantics
B(std::vector<X>&& vec) : vec_(std::move(vec)) {} // move semantics
};