C ++和C ++ 0x中const
的已知缺点是什么?
答案 0 :(得分:55)
const
唯一的问题是许多开发人员 严重低估了 。它是C ++工具箱中最好的工具之一,非常锋利,但却没有危险。
答案 1 :(得分:49)
主要问题是你必须写它。它应该是默认值,并且应明确指定所有可变变量或参数。
答案 2 :(得分:17)
const
的错误在于许多程序员似乎无法完全理解它,而“半常量正确”项目根本不起作用。这是您需要知道的:
Foo
与const Foo
(或Foo const
)Foo&
与const Foo&
(或Foo const&
)
Foo*
与const Foo*
(或Foo const*
)
Foo* const
和const Foo* const
(或Foo const* const
)void Foo::mutator()
与int Foo::accessor() const
的对比
iterator
与const_iterator
的对比
const iterator
和const const_iterator
从没有const概念的语言迁移到C ++非常困难,任何许多人都没有注意到这一点。
答案 3 :(得分:16)
我在新闻组中经常抱怨的两个主要问题是
需要浪费大量时间来支持非const感知API(尤其是Microsoft)。
need to define both const and non-const version of a method。
我认为后者可以/应该得到语言的支持。
可能与对协变成员函数实现的支持相结合,因为两者都需要一些方法来获取this
指针的类型。
第三个问题是
干杯&第h。,
答案 4 :(得分:3)
const的问题是程序员错误地使用它我们的不一致
答案 5 :(得分:3)
“错误”的一件事是你不能将T **转换成T const * const *,因为它不危险,所以应该允许这样做。不允许T **转换为T const **是正确的,该转换无效。
我有时会提到const实际上是一种将接口“拆分”为只读方法和编写方法的廉价方法。在C ++中它可能是不切实际的。尽管如此,在Java中使用ReadOnly版本的集合会更加实用,因为它们没有const,而且它们的集合类型更加面向对象。
const不会传播:这里的问题是,如果我在我的类中,constness不会被编译器“检查”,即我的接口类可以有一个“const”方法调用非const方法pImpl和编译器不会抱怨。这是因为我的const方法唯一保证不做的是将指针更改为指向不同的对象,而我的pImpl永远不会改变。它甚至可以是一个const指针(不是指向const的指针)。 shared_ptr<T>
和shared_ptr<const T>
之间缺乏适当的协方差也可能是一个问题,虽然总的来说我已经看到不是问题,但开发人员通常会输入他们的shared_ptrs并且很少typedef shared_ptr为const。并且它们有时会传递const shared_ptr<T> &
并认为它们正在传递一个指向const T的共享指针(与const T *一样),它们不是。
答案 6 :(得分:1)
“问题”?
如果您不打算修改传递指针的值(它纯粹用于函数的传递引用输入),请将其标记为const
。如果特定变量的值在初始化后不会改变,则同上。如果函数可以安全地调用const
类实例,请将其标记为const
。正确注释的项目越多const
,您在无意中犯错的可能性就越小,理论上在没有完整知识的情况下编译器能够执行的优化程度越高(例如在仅使用函数原型进行编译时) )。
当您尝试将const
变量转换为非const
变量时,现代版本的gcc支持警告。我建议你启用这些警告。
唯一需要注意的是你正在标记的 const
; const char * foo()
与char * foo() const
不同。
答案 7 :(得分:0)
另一个尚未提及的问题是设计糟糕的界面可能会破坏const(即使没有强制转换)。
示例:
class TreeNode {
public:
TreeNode& getParent() const { return *parent_; }
TreeNode& getLeft() const { return *left_; }
TreeNode& getRight() const { return *right_; }
private:
//TreeNode has a pointer to the Tree to enable navigation of the tree.
//Assume that other design constraints mean that this must be a pointer
//rather than a reference.
TreeNode* parent_;
TreeNode* left_;
TreeNode* right_;
};
//This function demonstrates the ability for const to be subverted.
TreeNode& remove_const(TreeNode const& toRemoveConstFrom) {
TreeNode& parent(toRemoveConstFrom.getParent());
TreeNode& leftChild(parent.getLeft());
TreeNode& rightChild(parent.getRight());
return &toRemoveConstFrom == &leftChild ? leftChild : rightChild;
}
const的不及物性质意味着可以有一个接口,可以从对象的const引用中获取对象的非const引用。在设计接口时需要注意这一点。
答案 8 :(得分:0)
下面的大部分答案陈述了诸如“const
的错误是X人做Y”这样的事情。这些不是答案,而是症状。那些const
没有问题。 {em>
答案 9 :(得分:0)
const
很棒。 const
很重要。 const
- 正确性是API良好的必要条件。
然而,我曾多次遇到const
两个问题。
无法追溯将变量标记为const
。您必须声明一个变量代码,在这种情况下,您有立即初始化它。但是,如果初始化代码包含if
怎么办?您可以选择省略const
(不合需要的),使用运算符?
而不是if
(危害可读性)。 Java是正确的,BTW - const
变量不必立即初始化,它们只需要在首次读取之前初始化,并且它们必须在 if
的所有分支。
无法指定通过引用函数传递的对象在函数调用期间不会更改。 const T& t
不意味着t
指向的对象不会更改,而只会使用引用t
来更改它。编译器仍然必须假设它没有看到的任何函数调用可能更改对象。在某些情况下,这可以防止相当多的优化。
答案 10 :(得分:-1)
一个问题是该语言还允许你const_cast它,这首先破坏了使用const的目的。
答案 11 :(得分:-2)
有一点是它仍有可能颠覆它。做这样的事情仍然是合法的:
void foo(const inst& x)
{
const_cast<int&> x = 3;
}
您甚至可以使用memset
之类的内容来破坏它而不使用明确的const_cast
。
这是在编译器强制执行const
和为非const
感知接口提供一些灵活性之间的权衡。
这导致了另一个限制,因为它没有被普遍接受,这部分是由于另一个问题,即使用const
是一个全有或全无的命题。如果您开始使用它,则需要在整个代码库中传播它。