C++ 对';没有匹配的成员函数调用;向后推';,共享指针向量

C++ 对';没有匹配的成员函数调用;向后推';,共享指针向量,c++,c++11,vector,shared-ptr,smart-pointers,C++,C++11,Vector,Shared Ptr,Smart Pointers,我有一个容器类,用于存储共享指针的向量。每当一个项目被附加到容器,我希望它承担该项目的所有权。换句话说,当解构容器时,它内部的所有元素也应该解构 template <typename T> class Container { private: const std::vector<std::shared_ptr<T>> vec_; public: void append(std::shared_ptr<T> item) {

我有一个
容器
类,用于存储共享指针的向量。每当一个项目被附加到
容器
,我希望它承担该项目的所有权。换句话说,当解构
容器时,它内部的所有元素也应该解构

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;
}
模板
类容器
{
私人:
常数std::向量向量向量;
公众:
无效附加(标准::共享的ptr项)
{
向量推回(标准::移动(项目));
}
无效打印元素()
{
对于(inti=0;istd::vector
vec
const
。这似乎会强制删除或禁用任何方法,例如尝试修改const向量的
push_back()


2020年5月10日新增: 我认为@ru毯fizz在其问题下的评论中的这一评论也值得阐述:


@GabrielStaples谢谢,移除
const
就成功了。我想
const
只能防止向量的重新分配,但允许它变异

我的答复是:

不,
const
这里适用于向量的内容。向量不是指针,但是你所说的可以用指针来完成,方法是使指针本身
const
而不是它指向
const
的内容。另外,
const
可变
是相反的。一个撤销其他。不能同时使两者生效。根据定义,常量是不可变的(不可更改),可变的是非常量

如何使指针常量而不是指针指向的内容?

首先,考虑原始代码(对它做了一些修改/修改):

请在此处自行在线运行:

1)之前的智能ptrs测试的cpp_模板_const_vector_。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;
}
下面是演示如何将常量指针指向非常量向量的新代码。请参阅我的评论,并研究更改:

请在此处自行在线运行:

2)在.cpp之后的智能ptrs测试的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;
}
原始答复: 在我看来,你的
std::vector
vec
const
。这似乎会强制删除或禁用任何方法,例如尝试修改const向量的
push_back()


2020年5月10日新增: 我认为@ru毯fizz在其问题下的评论中的这一评论也值得阐述:


@GabrielStaples谢谢,移除
const
就成功了。我想
const
只能防止向量的重新分配,但允许它变异

我的答复是:

不,
const
这里适用于向量的内容。向量不是指针,但是你所说的可以用指针来完成,方法是使指针本身
const
而不是它指向
const
的内容。另外,
const
可变
是相反的。一个撤销其他。不能同时使两者生效。根据定义,常量是不可变的(不可更改),可变的是非常量

如何使指针常量而不是指针指向的内容?

首先,考虑原始代码(对它做了一些修改/修改):

请在此处自行在线运行:

1)之前的智能ptrs测试的cpp_模板_const_vector_。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;
}
下面是演示如何将常量指针指向非常量向量的新代码。请参阅我的评论,并研究更改:

请在此处自行在线运行:

2)在.cpp之后的智能ptrs测试的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;
}

为什么不使用一个
唯一的\u ptr
?你的向量是常量。在我看来,这将强制删除或禁用任何方法,例如push_back,它试图修改常量向量。@Gabriels Staples谢谢,删除
常量
成功了。我认为
常量
只能防止
向量
的重新分配,但允许f或者它是变异的?@cigien这是一个调试另一个类的玩具示例,它需要
共享\u ptr
“我认为const只保护向量不被重新分配,但允许它变异?”不,
const
这里适用于向量的内容。向量不是指针,但是你所说的可以用指针来完成,方法是使指针本身
const
而不是它指向
const
的内容。另外,
const
可变
是相反的不能同时使两者都生效。根据定义,某些常量是不可变的(不可更改),一些可变的东西是非常量的。为什么不使用
唯一的\u ptr
?你的向量是常量。在我看来,它会强制删除或禁用任何方法,例如push_back,它试图修改常量向量。@Gabriels Staples谢谢,删除
常量
成功了。我认为
常量
只能防止重新分配nt的
向量
但允许它变异?@cigien这是一个调试另一个类的玩具示例,它需要
共享\u ptr
“我认为const只保护向量不被重新分配,但允许它变异?”不,
const
这里适用于向量的内容。向量不是指针,但是你所说的可以用指针来完成,方法是使指针本身
const
而不是它指向的内容
const
。另外,
const
可变
是相反的