我有一个Container
类,用于存储共享指针的向量。每当将项目附加到Container
时,我都希望它承担该项目的所有权。换句话说,当Container
被解构时,其内部的所有元素也应被解构。
template <typename T>
class Container
{
private:
const std::vector<std::shared_ptr<T>> vec_;
public:
void append(std::shared_ptr<T> item)
{
vec_.push_back(std::move(item));
}
void printElements()
{
for (int i = 0; i < vec_.size(); i++) { std::cout << vec_[i] << std::endl; }
}
};
int main(int argc, char** argv) {
std::unique_ptr<Container<std::string>> c = std::make_unique<Container<std::string>>();
c->append(std::make_shared<std::string>("hello"));
return 0;
}
问题是,我在vec_.push_back(std::move(item))
上收到以下错误。
No matching member function for call to 'push_back'
我不确定为什么会发生此错误。
您的std::vector
,vec_
为const
。在我看来,这将强制删除或禁用任何试图修改const向量的方法,例如push_back()
。
[我认为也有必要在他的问题下的评论中详细说明@Carpetfizz的评论:
@@ GabrielStaples,谢谢,删除
const
可以解决问题。我以为const
仅防止对vector_进行重新分配,但允许对其进行突变?
我的回复:
否,
const
在此适用于向量的内容。向量不是指针,但是您要使用指针可以通过使指针本身为const
而不是其指向const
的内容来完成。另外,const
和mutable
是相反的。一个撤消另一个。您不能同时使两者同时生效。根据定义,某些常量是不可变的(不可更改),而某些可变对象是非常量的。
并且如何使一个指针成为const而不是它指向的内容?
首先,请考虑原始代码(我对此做了一些小的修改/修复):
在此处在线运行:https://onlinegdb.com/SyMqoeU9L
1)cpp_template_const_vector_of_smart_ptrs_test_BEFORE.cpp:
#include <iostream>
#include <memory>
#include <vector>
template <typename T>
class Container
{
private:
// const std::vector<std::shared_ptr<T>> vec_; // does NOT work
std::vector<std::shared_ptr<T>> vec_; // works!
public:
void append(std::shared_ptr<T> item)
{
vec_.push_back(std::move(item));
}
void printElements()
{
for (int i = 0; i < vec_.size(); i++)
{
// Don't forget to dereference the pointer with `*` in order to
// obtain the _contens of the pointer_ (ie: what it points to),
// rather than the pointer (address) itself
std::cout << *vec_[i] << std::endl;
}
}
};
int main(int argc, char** argv)
{
std::unique_ptr<Container<std::string>> c = std::make_unique<Container<std::string>>();
c->append(std::make_shared<std::string>("hello"));
c->append(std::make_shared<std::string>("world"));
c->printElements();
return 0;
}
输出:
hello
world
这是新代码,演示了如何使指向非常量向量的常量指针。在这里查看我的评论,并研究更改:
在此处在线运行:https://onlinegdb.com/HyjNx-L5U
2)cpp_template_const_vector_of_smart_ptrs_test_AFTER.cpp
#include <iostream>
#include <memory>
#include <vector>
template <typename T>
class Container
{
private:
// const std::vector<std::shared_ptr<T>> vec_; // does NOT work
// Create an alias to this type just to make the creation below less
// redundant in typing out the long type
using vec_type = std::vector<std::shared_ptr<T>>;
// NON-const object (vector)--so it can be changed
vec_type vec_;
// const pointer to NON-const object--so, vec_p_ can NOT be re-assigned to
// point to a new vector, because it is `const`! But, **what it points to**
// CAN be changed because it is NOT const!
vec_type * const vec_p_ = &vec_;
// To prove that vec_p_ can NOT be re-assigned to point to a new vector,
// watch this:
vec_type vec2_;
// vec_p_ = &vec2_; // COMPILE-TIME ERROR! Here is the error:
// main.cpp:44:5: error: ‘vec_p_’ does not name a type; did you mean ‘vec_type’?
// vec_p_ = &vec2_; // COMPILE-TIME ERROR!
// ^~~~~~
// vec_type
// BUT, this works just fine:
vec_type * vec_p2_ = &vec2_; // non-const pointer to non-const data
public:
void append(std::shared_ptr<T> item)
{
vec_p_->push_back(std::move(item));
}
void printElements()
{
for (int i = 0; i < vec_p_->size(); i++)
{
// Notice we have to use a double de-reference here now!
std::cout << *(*vec_p_)[i] << std::endl;
}
}
};
int main(int argc, char** argv)
{
std::unique_ptr<Container<std::string>> c = std::make_unique<Container<std::string>>();
c->append(std::make_shared<std::string>("hello"));
c->append(std::make_shared<std::string>("world"));
c->printElements();
return 0;
}
输出:
hello
world