【问题标题】:No matching member function call to 'push_back', vector of shared pointers没有匹配的成员函数调用“push_back”,共享指针向量
【发布时间】:2020-08-25 16:00:15
【问题描述】:

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

我不确定为什么会出现这个错误。

【问题讨论】:

  • 为什么不使用unique_ptr
  • 你的 vec_ 是常量。在我看来,这将强制删除或禁用任何方法,例如 push_back,它试图修改 const 向量。
  • @GabrielStaples 谢谢,删除const 成功了。我以为const 只能防止vector_ 的重新分配,但允许它发生突变?
  • @cigien 这是一个调试另一个需要shared_ptr的类的玩具示例
  • “我认为 const 只是防止 vector_ 重新分配,但允许它被突变?”不,const 这里适用于向量的内容。向量不是指针,但你所说的可以用指针来完成,通过使指针本身const 而不是它指向const 的内容。此外,constmutable 是相反的。一个撤消另一个。您不能同时使两者生效。根据定义,恒定的东西是不可变的(不可改变的),而可变的东西是非常量的。

标签: c++ c++11 vector shared-ptr smart-pointers


【解决方案1】:

原答案:

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


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

我认为在他的问题下,@Carpetfizz 在 cmets 中的这条评论也是值得阐述的:

@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

这里的新代码演示了如何创建一个指向非常量向量的常量指针。在这里查看我的 cmets,并研究更改:

在这里自己在线运行: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_;

    // This also does NOT work (in place of the line above) because it makes 
    // the **contents of what you're pointing to const**, which means again 
    // that the contents of the vector can NOT be modified. 
    // const vec_type * const vec_p_ = &vec_; // does NOT work 
    // Here's the compile-time error in gcc when compiling for C++17:
    //      main.cpp: In instantiation of ‘void Container<T>::append(std::shared_ptr<_Tp>) [with T = std::basic_string<char>]’:
    //      <span class="error_line" onclick="ide.gotoLine('main.cpp',78)">main.cpp:78:53</span>:   required from here
    //      main.cpp:61:9: error: passing ‘const vec_type {aka const std::vector >, std::allocator > > >}’ as ‘this’ argument discards qualifiers [-fpermissive]
    //               vec_p_->push_back(std::move(item));
    //               ^~~~~~
    //      In file included from /usr/include/c++/7/vector:64:0,
    //                       from main.cpp:22:
    //      /usr/include/c++/7/bits/stl_vector.h:953:7: note:   in call to ‘void std::vector<_Tp, _Alloc>::push_back(std::vector<_Tp, _Alloc>::value_type&&) [with _Tp = std::shared_ptr >; _Alloc = std::allocator > >; std::vector<_Tp, _Alloc>::value_type = std::shared_ptr >]’
    //             push_back(value_type&& __x)
    //             ^~~~~~~~~


    // 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

【讨论】:

  • 非常感谢您提供更多详细信息!
猜你喜欢
  • 2015-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-09-11
  • 2012-12-16
  • 2016-08-09
  • 1970-01-01
相关资源
最近更新 更多