vector :: push_back从const Type *转换为type *

时间:2014-12-31 19:03:35

标签: c++ vector const const-cast

vector::push_back的签名是:

void push_back (const value_type& val);

这意味着它有责任不破坏val

我的功能是:

Result User::addFriend(const User* newFriend)
{
    // check that newFriend is valid and is not already a friend
    if (newFriend == NULL || isFriend(newFriend)) return FAILURE;
    friends_.push_back(newFriend);
    friendsNum_++;
    return SUCCESS;
}

当我编译.c文件时,我收到编译错误:

invalid conversion from 'const User*' to 
std::vector User*::value_type
  1. 如果 push_back 承诺不改变 val ,为什么会出现此错误?

  2. 克服错误的正确和干净方法是什么?也许是通过 const_cast

  3. 谢谢你!

    User.h:

    class User {
    ...
    public:
        vector<User*> friends_;
    ...
    }
    

5 个答案:

答案 0 :(得分:6)

您正在存储指针向量:

std::vector<User*> friends_;
然而,这种方法存在问题。请注意,这些指针不是const User*:任何有权限friends_的人都可以自由修改User

此处vector中的类型参数为User*,而非User,即value_type ≡ User。因此,这一行

void push_back (const value_type& val);

应解释如下:

void push_back (const User*& val);

请注意the syntax is a bit misleading here;一个更清晰的方式来看待它:

void push_back (User *const &val);

const修改左侧的内容:它可以防止指针被更改,但它不会阻止底层User本身被更改。

由于const仅影响指针而不影响User,因此传入const User*会违反合同:

Result User::addFriend(const User* newFriend){
    …
    friends_.push_back(newFriend);
    …
}

你不能这样做。由于addFriend承诺不会阻止User被更改,因此将其存储到非const User*的向量中将允许任何有权访问该向量的人但请他们修改User

可能的解决方案:

  • addFriendUser*而不是const User*。更好的是:使用引用,除非你有充分的理由不这样做。
  • friends_更改为使用const User*而不是User*。更好的是:直接存储User而不是指针。
  • 制作User
  • 的副本

答案 1 :(得分:5)

您的代码存在逻辑问题。也就是说,您存储指向可修改对象的指针:

vector<User*> friends_;

然而你的addFriend()方法接受一个指向const对象的指针:

Result User::addFriend(const User* newFriend) 
//                     ^^^^^
{
    // stuff..
    friends_.push_back(newFriend);
}

那些不排队。实际上,push_back必须将const User*转换为User*,因此编译错误。应更改这些类型中的一种或另一种。 friends_需要vector<const User*>(如果你真的无意修改这些对象)或addFriend需要User*(如果你这样做)。不要使用const_cast

答案 2 :(得分:0)

由于Collin Dauphinee,我想我想通了。 无法将User *添加到非const User *的矢量。

声明应该在.h文件中更新:

class User{
...
public:
    vector<const User*> friends_;
...
}

答案 3 :(得分:0)

建议您为friends_ member使用共享ptr或uniquer ptr。因此,最佳做法是声明friends_(如果朋友将被分享):

typedef std::shared_ptr<User> sharedUsers;
std::vector< sharedUsers> friends_

或者如果您的朋友不会被分享:

typedef std::unique_ptr<User> sharedUsers;
std::vector<sharedUsers> friends_

通过这种方式,所有内存管理都将委派给您的智能指针。

答案 4 :(得分:0)

因为签名而引起混淆:

void push_back (const value_type& val);

不会转换为此(使用User*实例化向量时)。

void push_back (const User * & val); //wrong. but visually looks same!

相反,它转换为

void push_back (User * const & val);  //right. but visually looks different

现在,为什么类型const User*的对象无法传递给此函数变得更加清晰,因为:

  • const User *表示指针指向的对象是const。指针本身是非常量的。

  • User *const表示指针指向的对象是非const。指针本身就是const。

请注意,const User*User const*恰好代表相同的事物。

这是我更喜欢在模板中输入类型名称之后写const的原因之一。如果程序员养成这种习惯,那么push_back函数将如下所示:

void push_back(value_type const & val);

当用User*实例化时,我们可以很容易地将程序员翻译成:

void push_back(User * const & val); //right. visually similar as well.

这正是应该的样子。

希望有所帮助。