没有匹配的成员函数调用'push_back',共享指针的向量

问题描述 投票:1回答:1

我有一个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'

我不确定为什么会发生此错误。

c++ c++11 vector shared-ptr smart-pointers
1个回答
3
投票

原始答案:

您的std::vectorvec_const。在我看来,这将强制删除或禁用任何试图修改const向量的方法,例如push_back()


[2020年5月10日添加的新增内容:

[我认为也有必要在他的问题下的评论中详细说明@Carpetfizz的评论:

@@ GabrielStaples,谢谢,删除const可以解决问题。我以为const仅防止对vector_进行重新分配,但允许对其进行突变?

我的回复:

否,const在此适用于向量的内容。向量不是指针,但是您要使用指针可以通过使指针本身为const而不是其指向const的内容来完成。另外,constmutable是相反的。一个撤消另一个。您不能同时使两者同时生效。根据定义,某些常量是不可变的(不可更改),而某些可变对象是非常量的。

并且如何使一个指针成为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
© www.soinside.com 2019 - 2024. All rights reserved.