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
如果 push_back 承诺不改变 val ,为什么会出现此错误?
克服错误的正确和干净方法是什么?也许是通过 const_cast ?
User.h:
class User {
...
public:
vector<User*> friends_;
...
}
答案 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
。
可能的解决方案:
addFriend
取User*
而不是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.
这正是应该的样子。
希望有所帮助。