注意:答案是按照特定的顺序给出的,但由于许多用户根据投票而不是给出的时间对答案进行排序,因此这里是答案的索引,它们是最有意义的顺序:
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)
什么是"序列点"?
未定义的行为和序列点之间的关系是什么?
我经常使用有趣和复杂的表达方式a[++i] = i;,让自己感觉更好.我为什么要停止使用它们?
如果您已阅读此内容,请务必访问后续问题重新加载未定义的行为和序列点.
(注意:这是Stack Overflow的C++常见问题解答的一个条目.如果你想批评在这种形式下提供常见问题解答的想法,那么发布所有这些的元数据的发布将是这样做的地方.这个问题在C++聊天室中受到监控,其中FAQ的想法一开始就出现了,所以你的答案很可能被那些提出想法的人阅读.)
在C++中初始化私有静态数据成员的最佳方法是什么?我在头文件中尝试了这个,但它给了我奇怪的链接器错误:
class foo
{
private:
static int i;
};
int foo::i = 0;
Run Code Online (Sandbox Code Playgroud)
我猜这是因为我无法从课外初始化私人成员.那么最好的方法是什么?
为什么第一个返回引用?
int x = 1;
int y = 2;
(x > y ? x : y) = 100;
Run Code Online (Sandbox Code Playgroud)
而第二个不?
int x = 1;
long y = 2;
(x > y ? x : y) = 100;
Run Code Online (Sandbox Code Playgroud)
实际上,第二个根本没有编译 - "没有左边的赋值".
为什么以下工作?
void foo() {
cout << "Foo to you too!\n";
};
int main() {
void (*p1_foo)() = foo;
void (*p2_foo)() = *foo;
void (*p3_foo)() = &foo;
void (*p4_foo)() = *&foo;
void (*p5_foo)() = &*foo;
void (*p6_foo)() = **foo;
void (*p7_foo)() = **********************foo;
(*p1_foo)();
(*p2_foo)();
(*p3_foo)();
(*p4_foo)();
(*p5_foo)();
(*p6_foo)();
(*p7_foo)();
}
Run Code Online (Sandbox Code Playgroud) 在C++中通过值传递或通过常量引用传递是否更好?
我想知道哪个是更好的做法.我意识到通过常量引用传递应该在程序中提供更好的性能,因为你没有复制变量.
C++ 11 std::move(x)函数根本不会移动任何东西.它只是一个转换为r值.为什么这样做?这不是误导吗?
我发现自己并没有完全理解它的逻辑std::move().
起初,我用谷歌搜索它,但似乎只有关于如何使用的文件std::move(),而不是它的结构如何工作.
我的意思是,我知道模板成员函数是什么,但是当我std::move()在VS2010中查看定义时,它仍然令人困惑.
std :: move()的定义如下.
template<class _Ty> inline
typename tr1::_Remove_reference<_Ty>::_Type&&
move(_Ty&& _Arg)
{ // forward _Arg as movable
return ((typename tr1::_Remove_reference<_Ty>::_Type&&)_Arg);
}
Run Code Online (Sandbox Code Playgroud)
首先对我来说奇怪的是参数,(_Ty && _Arg),因为当我调用函数时,如下所示,
// main()
Object obj1;
Object obj2 = std::move(obj1);
Run Code Online (Sandbox Code Playgroud)
它基本上等于
// std::move()
_Ty&& _Arg = Obj1;
Run Code Online (Sandbox Code Playgroud)
但正如您已经知道的那样,您不能直接将LValue链接到RValue引用,这让我觉得它应该是这样的.
_Ty&& _Arg = (Object&&)obj1;
Run Code Online (Sandbox Code Playgroud)
但是,这是荒谬的,因为std :: move()必须适用于所有值.
所以我想要完全理解它是如何工作的,我也应该看看这些结构.
template<class _Ty>
struct _Remove_reference
{ // remove reference
typedef _Ty _Type;
};
template<class _Ty>
struct _Remove_reference<_Ty&>
{ // remove reference
typedef _Ty _Type;
}; …Run Code Online (Sandbox Code Playgroud) 我可以'some'在MSVC生成的汇编代码中看到两个文字,但只有一个有clang和gcc.这导致完全不同的代码执行结果.
static const char *A = "some";
static const char *B = "some";
void f() {
if (A == B) {
throw "Hello, string merging!";
}
}
Run Code Online (Sandbox Code Playgroud)
任何人都可以解释这些编译输出之间的差异和相似之处吗?为什么即使没有请求优化,clang/gcc也会优化某些内容?这是某种未定义的行为吗?
我还注意到,如果我将声明更改为下面显示的声明,则clang/gcc/msvc根本不会"some"在汇编代码中留下任何声明.为什么行为不同?
static const char A[] = "some";
static const char B[] = "some";
Run Code Online (Sandbox Code Playgroud) 我正在学习C++,并试着避免养成坏习惯.根据我的理解,clang-tidy包含许多"最佳实践",我尽可能地尽可能地坚持它们(即使我不一定理解为什么它们被认为是好的),但我不确定我是否了解这里推荐的内容.
我在教程中使用了这个类:
class Creature
{
private:
std::string m_name;
public:
Creature(const std::string &name)
: m_name{name}
{
}
};
Run Code Online (Sandbox Code Playgroud)
这导致了一个讽刺的建议,即我应该通过值而不是引用和使用std::move.如果我这样做,我得到的建议做出name的引用(以确保它不会被复制每次),并警告说std::move将不会有任何影响,因为name是const这样,我应该将其删除.
我没有得到警告的唯一方法是const完全删除:
Creature(std::string name)
: m_name{std::move(name)}
{
}
Run Code Online (Sandbox Code Playgroud)
这似乎是合乎逻辑的,因为唯一的好处const是防止弄乱原始字符串(这不会因为我通过值传递而发生).但我在CPlusPlus.com上看到了:
虽然注意到-in标准库移动意味着移动的对象保持有效但未指定的状态.这意味着,在这样的操作之后,移动对象的值应该只被销毁或分配一个新值; 访问它否则会产生一个未指定的值.
现在想象一下这段代码
std::string nameString("Alex");
Creature c(nameString);
Run Code Online (Sandbox Code Playgroud)
因为nameString通过值传递,std::move只会name在构造函数内部无效而不会触及原始字符串.但这有什么好处?看起来无论如何内容只被复制一次 - 如果我在调用时通过引用传递m_name{name},如果我在传递它时传递值(然后它被移动).我知道这比通过值而不是使用std::move(因为它被复制两次)更好.
所以有两个问题:
std::move过度引用和调用是否有任何好处m_name{name}?