从Effective C++,第3项
/* case1 */ const std::vector<int>::iterator i // i acts like a T* const
/* case2 */ std::vector<int>::const_iterator ci // ci acts like a const T*
Run Code Online (Sandbox Code Playgroud)
基本上'const'适用于其左边的任何东西(除非没有任何东西,在这种情况下它适用于它的直接权利).
当我第一次阅读本书中的第3项时,我预计它将在case1和case2中反过来.
我应该把这个案子当作例外吗?或者是否有一些我缺失的更深层次的理解?
我的问题是关于"Effective C++"一书的特定项目(3).本书给出了这个例子,我尝试尽可能接近vs 2010 c ++(包括iostream和string):
class TextBlock {
public:
const char& operator[](std::size_t pos) const
{
return text[pos];
}
char& operator[](std::size_t pos)
{
return text[pos];
}
private:
std::string text;
};
void print(const TextBlock& ctb)
{
std::cout << ctb[0]; // OK
//ctb[0] = ‘A’; // Not OK – compiler error
}
int _tmain(int argc, _TCHAR* argv[])
{
TextBlock tb(“Hello”);
std::cout << tb[0];
tb[0] = ‘x’; // OK because return has &, not const
const TextBlock ctb("World");
std::cout << ctb[0];
return 0;
} …Run Code Online (Sandbox Code Playgroud) 我正在尝试遵循 Scott Meyers 在更有效的 C++ 第 22 条中的建议:“考虑使用op=而不是独立op”。他建议我们可以创建一个模板operator+,以便所有实现的类operator+=自动获得operator+:
template<class T>
const T operator+(const T& lhs, const T& rhs)
{
return T(lhs) += rhs;
}
Run Code Online (Sandbox Code Playgroud)
现在,在《Effective Modern C++》第 25 条中,有一个矩阵加法的示例(第 172 页),其中operator+建议使用右值重载 ,因为如果您知道lhs或rhs是右值,则可以使用它们来存储结果,从而防止可能巨大的矩阵的无用副本。所以我添加了重载:
template<class T>
T operator+(T&& lhs, const T& rhs)
{
return std::move(lhs += rhs);
}
template<class T>
T operator+(T const& lhs, T&& rhs)
{
return std::move(rhs += lhs);
}
template<class T>
T operator+(T&& …Run Code Online (Sandbox Code Playgroud) c++ templates operator-overloading effective-c++ overload-resolution
我正在阅读Scott Meyers的Effective Modern C++,我在我的机器上尝试了他为Deducing Types章节提供的示例.
他提供这个功能:
template <typename Container, typename Index>
auto decltype_test_1(Container& c, Index i) -> decltype(c[i])
{
return c[i];
}
Run Code Online (Sandbox Code Playgroud)
然后它以这种方式使用该功能:
std::deque<int> d;
…
decltype_test_1(d, 5) = 10; // authenticate user, return d[5],
// then assign 10 to it;
// this won't compile!
Run Code Online (Sandbox Code Playgroud)
说它不会编译.我试过MSVC,它确实编译.我写了以下内容main:
std::deque<int> d;
d.push_back(0);
d.push_back(1);
d.push_back(2);
decltype_test_1(d, 0) = 10;
for each (auto item in d)
cout << item << endl;
Run Code Online (Sandbox Code Playgroud)
我不明白为什么它编译,最重要的是,它显示10为双端队列的第一个元素.他解释说这个代码是错误的.它为什么在这里工作?我错过了什么?
众所周知,在 x86/x86_64 等多字节字计算机中,逐字复制/移动大量内存(每步 4 或 8 个字节)比逐字节复制/移动更有效。
我很好奇 strncpy/memcpy/memmove 会以哪种方式做事,以及它们如何处理内存字对齐。
char buf_A[8], buf_B[8];
// I often want to code as this
*(double*)buf_A = *(double*)buf_B;
//in stead of this
strcpy(buf_A, buf_B);
// but it worsen the readability of my codes.
Run Code Online (Sandbox Code Playgroud) 我有几个我不想复制的类,其中一些类有指针数据成员.为了使这些类不可复制,我私下继承了以下类模板:
template <class T>
class Uncopyable
{
protected:
Uncopyable() {}
virtual ~Uncopyable() {}
private:
Uncopyable(const Uncopyable &);
T & operator=(const T&);
};
Run Code Online (Sandbox Code Playgroud)
我这样使用的是:
class Entity : private Uncopyable<Entity> { }
Run Code Online (Sandbox Code Playgroud)
这工作正常,但是当我使用-Weffc ++编译时,我仍然收到以下警告:
class Entity has pointer data members
but does not override Entity(const Entity&)
or operator=(const Entity&)
Run Code Online (Sandbox Code Playgroud)
为什么它仍然给我这个警告?
众所周知,由于作用域,从C++中的函数返回局部变量是不安全的.在Effective C++第三版中,Scott Meyers在第21页的第21项中讲述了这个问题.然而,最后他说,正确的决定将是:
inline const Rational operator*(const Rational& lhs, const Rational& rhs) {
return Rational(lhs.n * rhs.h, lhs.d * rhs.d);
}
Run Code Online (Sandbox Code Playgroud)
这不是一个坏习惯,这个功能不安全吗?
UPD:谢谢大家的解释.
我正在读这本书,我不明白两段代码之间的区别.
class Bitmap{...};
class Widget
{
...
private:
Bitmap* m_pb;
};
Widget& Widget::operator=(const Widget& rhs)
{
if (this == &rhs)
{
return *this; // if a self-assignment, do nothing
}
delete pb;
pb = new Bitmap(*rhs.m_pb);
return *this;
}
Run Code Online (Sandbox Code Playgroud)
迈尔斯先生说:
如果"new Bitmap"表达式产生异常,则Widget将最终保持指向已删除Bitmap的指针.
这是否意味着pd指针指向NULL?
Widget& Widget::operator=(const Widget& rhs)
{
Bitmap* temp = pb;
pb = new Bitmap(*rhs.pb);
delete temp;
return *this;
}
Run Code Online (Sandbox Code Playgroud)
迈尔斯先生说:
现在,如果"new Bitmap"抛出异常,pb指针保持不变.
据我所知,临时指针指向与pb指针相同的内存地址.如果"new"抛出异常,pb将指向NULL,下一句将删除Bitmap.那是对的吗?我没有看到这些实现之间的区别.
提前致谢.