我刚刚了解到C++中前缀增量运算符的结果是左值.有可能这种行为有助于程序员更有效,但我想不到任何.前缀增量运算符的这种行为有哪些惯用的用法?
以下是Effective Modern C++(第55页)的引用:
"假设你使用一组空的大括号来构造一个支持默认构造函数的对象,并且还支持std :: initializer_list构造.你的空括号是什么意思?等规则是你得到默认构造."
我用std :: array尝试过这个:
std::array<int, 10> arr{};
Run Code Online (Sandbox Code Playgroud)
并得到了g ++(版本4.8.2)的警告:
警告:缺少成员'std :: array <int,10ul> :: _ M_elems'的初始值设定项
这是在尝试std::array从空构造一个时得到的警告std::initializer_list(请参阅为什么我可以从{}初始化一个常规数组,而不是std :: array来讨论此警告).
那么,为什么上面的代码行不能解释为调用默认构造函数?
更新:我在这里问了一个较窄的问题.
在现代C++设计的第6-7页,Andrei Alexandrescu 就构建灵活设计两个C++语言特性(多重继承和模板)的优缺点进行了非常基础的讨论.他的结论是:
现在将多重继承的缺点列表与模板的缺点列表进行比较.有趣的是,多重继承和模板促进了互补的权衡.多重遗传有很少的机制; 模板有丰富的机制.多重继承会丢失模板中充斥的类型信息.模板的专业化不能扩展,但多重继承可以很好地扩展.您只能为模板成员函数提供一个默认值,但您可以编写无限数量的基类.
我能感觉到安德烈在这里所说的非常重要,但我无法真正理解所说的内容,没有任何例子来说明这些要点.这个问题要求提供简单的例子来说明这些要点(请继续阅读).
为了使问题更具体,我想请您关注多重继承的弱点.这就是安德烈对他们所说的话(根据我对上下文的理解,方括号中的文字是我的):
在这样的设置[即多重继承 ],[构建一个灵活的
SmartPtr],用户将通过继承一些BaseSmartPtr类和两个类来构建一个多线程,引用计数的智能指针类:MultiThreaded和RefCounted.任何经验丰富的班级设计师都知道这种天真的设计不起作用.分析多重继承无法创建灵活设计的原因,为获得完善的解决方案提供了有趣的思路.使用多重继承来组装单独功能的问题如下:
- 力学.没有样板代码以受控方式组装继承的组件.组合BaseSmartPtr,MultiThreaded和RefCounted的唯一工具是一种称为多重继承的语言机制.该语言在组合基类时应用简单的叠加,并建立一组用于访问其成员的简单规则.除最简单的情况外,这是不可接受的.大多数情况下,您需要仔细编排继承类的工作方式以获得所需的行为.
- 输入信息.基类没有足够的类型信息来执行其任务.例如,假设您尝试通过从DeepCopy基类派生来为智能指针类实现深层复制.但是DeepCopy有什么接口?它必须创建一个它不知道的类型的对象.
- 国家操纵.使用基类实现的各种行为方面必须操纵相同的状态.这意味着它们必须使用虚拟继承来继承保存状态的基类.这使设计复杂化并使其更加严格,因为前提是用户类继承库类,反之亦然.
我非常感谢上面三个项目中的每个项目的简单示例.每个例子都会显示多重继承的一个限制(例如,差的机制)以及模板如何不具备这种限制(Andrei写道" 多重继承和模板促进互补权衡").
假设层次结构的所有类都实现了模板成员函数g.所有类共享两个其他函数的相同实现,f1并f2调用此模板:
struct A {
virtual void f1() {
g(5);
}
virtual void f2() {
g(5.5);
}
private:
template <typename T> void g(T) {std::cout << "In A" << std::endl;}
};
struct B: A {
// Can I get rid of this duplicate code?
virtual void f1() {
g(5);
}
virtual void f2() {
g(5.5);
}
private:
template <typename T> void g(T) {std::cout << "In B" << std::endl;}
};
struct C: A {
// Can I …Run Code Online (Sandbox Code Playgroud) 编译器不应该为声明析构函数或复制操作(即复制构造函数/赋值)的类合成移动操作的规则是有意义的.毕竟,通过宣布这些操作,该课程承认它需要做一些自定义簿记.
但是,当类将析构函数或复制操作定义为=default?时,这种推理不适用?那么这种情况不应该是规则的例外吗?
编辑:我可能想要将析构函数定义为=default但不是其他特殊操作的一个原因是当我需要基类的虚拟析构函数时,所以我被迫定义一个使其成为虚拟的.
我正在使用Mono compiler v4.2.1(.NETFramework 4.5)编译以下代码:
Module Module1
Sub Change(ByRef x As Integer)
x += 1
End Sub
Sub Main()
Dim arr() As Integer = {1}
Change(arr(0))
Console.WriteLine(arr(0))
End Sub
End Module
Run Code Online (Sandbox Code Playgroud)
生成的输出是:1.为什么x参数不通过引用绑定到数组元素?有没有办法让这项工作无需传递数组?
其他细节:
我通过HackerRank运行上面的代码
从Visual Studio 2010/2012运行时,上面的代码生成2的输出.
不确定动机是否对问题很重要,但通过引用传递数组元素非常有用.例如,可以实现Swap两个数组元素.
《竞争性程序员手册》第 99 页建议采用以下方法来遍历集合的所有子集x(集合位代表集合中的数字):
int b = 0;
do {
// Process subset b
} while (b = (b - x) & x);
Run Code Online (Sandbox Code Playgroud)
我了解有关位表示和按位运算符的所有背景知识。我不明白的是为什么b = (b - x) & x会导致获得下一个子集。
这篇文章给出了一个例子,但没有提供见解。那么,为什么这会起作用呢?
假设以下策略类负责算法的一个方面:
struct VoidF {
static void f() {
... // some code that has side effects
}
};
struct BoolF {
static bool f() {
bool res = ...; // some computation
return res;
}
};
Run Code Online (Sandbox Code Playgroud)
该BoolF政策是"增强感知":当BoolF :: f()的返回true,该算法可以退出.VoidF是"增强 - 不知道",因此它返回void(我不想强迫我的库的用户返回,bool当它对他没有任何意义).
该算法目前编写如下:
template <typename F>
struct Algorithm {
void run() {
... // some computation here
if (std::is_same<decltype(F::f()), bool>::value) {
if (F::f()) return;
} else
F::f(); // If F is …Run Code Online (Sandbox Code Playgroud) 从1.8.0版开始,doxygen 支持 markdown.对于习惯的人来说org-mode,写入org-mode和导出的选择markdown可能很有吸引力.由于markdown实施与标准doxygen略有不同markdown,我想问:有没有人尝试过这个工作流程?用这种方式编写文档时应该记住什么?
我理解(这是一个来源),只要两个定义不冲突,就可以重新定义默认模板参数。因此,我尝试使用 g++ 5.3.1 编译以下内容:
\n\ntemplate <class = int> class A; // forward declaration\ntemplate <class T = A<>> struct B {};\n\ntemplate <class T = int> class A {}; // "= int" here is for clarity\n\nint main() { return 0; }\nRun Code Online (Sandbox Code Playgroud)\n\n编译器抱怨:
\n\n\n\n\n错误:重新定义 \xe2\x80\x98class T\xe2\x80\x99 的默认参数
\n
我的理解哪里不对?
\n