在C中,可以在声明中使用字符串文字,如下所示:
char s[] = "hello";
Run Code Online (Sandbox Code Playgroud)
或者像这样:
char *s = "hello";
Run Code Online (Sandbox Code Playgroud)
那么区别是什么呢?我想知道在编译和运行时的存储持续时间实际发生了什么.
我经常发现自己处于一种情况,我在C++项目中面临多个编译/链接器错误,因为一些糟糕的设计决策(由其他人做出:))导致不同头文件中C++类之间的循环依赖(也可能发生)在同一个文件中).但幸运的是(?)这种情况经常不足以让我在下次再次发生问题时记住这个问题的解决方案.
因此,为了便于将来回忆,我将发布一个代表性问题和解决方案.更好的解决方案当然是受欢迎的.
A.h
class B;
class A
{
int _val;
B *_b;
public:
A(int val)
:_val(val)
{
}
void SetB(B *b)
{
_b = b;
_b->Print(); // COMPILER ERROR: C2027: use of undefined type 'B'
}
void Print()
{
cout<<"Type:A val="<<_val<<endl;
}
};
Run Code Online (Sandbox Code Playgroud)B.h
#include "A.h"
class B
{
double _val;
A* _a;
public:
B(double val)
:_val(val)
{
}
void SetA(A *a)
{
_a = a;
_a->Print();
}
void Print()
{
cout<<"Type:B val="<<_val<<endl;
}
};
Run Code Online (Sandbox Code Playgroud)main.cpp
#include "B.h" …Run Code Online (Sandbox Code Playgroud)我有一个A类,它有两个静态变量.我想用另一个不相关的静态变量初始化一个,就像这样:
#include <iostream>
class A
{
public:
static int a;
static int b;
};
int A::a = 200;
int a = 100;
int A::b = a;
int main(int argc, char* argv[])
{
std::cout << A::b << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出是200.所以,谁能告诉我为什么?
看来 GCC 和 Clang 对有符号整数和无符号整数之间的加法的解释不同,具体取决于它们的大小。为什么会这样?所有编译器和平台上的转换是否一致?
举个例子:
#include <cstdint>
#include <iostream>
int main()
{
std::cout <<"16 bit uint 2 - int 3 = "<<uint16_t(2)+int16_t(-3)<<std::endl;
std::cout <<"32 bit uint 2 - int 3 = "<<uint32_t(2)+int32_t(-3)<<std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
结果:
$ ./out.exe
16 bit uint 2 - int 3 = -1
32 bit uint 2 - int 3 = 4294967295
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,我们都得到 -1,但其中一个被解释为无符号整数并下溢。我本以为两者都会以相同的方式进行转换。
那么,为什么编译器对它们的转换如此不同,这能保证一致吗?我用 g++ 11.1.0、clang 12.0 对此进行了测试。以及 Arch Linux 和 Debian 上的 g++ 11.2.0,得到相同的结果。
以下程序抛出nullptr异常,然后捕获异常int*:
#include <iostream>
int main() {
try {
throw nullptr;
}
catch(int*) {
std::cout << "caught int*";
}
catch(...) {
std::cout << "caught other";
}
}
Run Code Online (Sandbox Code Playgroud)
在 Clang 和 GCC 中,程序成功打印caught int*, demo: https://gcc.godbolt.org/z/789639qbb
但是在 Visual Studio 16.11.2 中,程序打印caught other. 这是 MSVC 中的错误吗?
为了使对象不可复制,我们可以显式删除其复制构造函数和复制分配运算符。
我的问题是:什么是做正确的地方-在public,private或protected之类的部分?并且-这种选择有什么区别吗?
这是复制构造函数[class.copy.ctor / 1]的定义:
如果类X的非模板构造函数的第一个参数为X&,const X&,volatile X&或const volatile X&类型,并且没有其他参数,或者所有其他参数都具有默认参数([dcl。 fct.default])。
为什么标准将模板排除为复制构造函数?
在这个简单的示例中,两个构造函数都是副本构造函数:
struct Foo {
Foo(const Foo &); // copy constructor
Foo(Foo &); // copy constructor
};
Run Code Online (Sandbox Code Playgroud)
参见以下类似示例:
struct Foo {
Foo() = default;
template <typename T>
Foo(T &) {
printf("here\n");
}
};
int main() {
Foo a;
Foo b = a;
}
Run Code Online (Sandbox Code Playgroud)
在此示例中,here将被打印。因此,似乎我的模板构造函数是一个复制构造函数,至少它的行为类似于一个(在通常调用复制构造函数的上下文中被调用)。
为什么文本中存在“非模板”要求?
参考这个问题.用于初始化constexpr变量的核心常量表达式是错误的y.这么多是给定的.
但如果我试着if变成if constexpr:
template <typename T>
void foo() {
constexpr int x = -1;
if constexpr (x >= 0){
constexpr int y = 1 << x;
}
}
int main(){
foo<int>();
}
Run Code Online (Sandbox Code Playgroud)
错误仍然存在.GCC 7.2仍然给出:
error: right operand of shift expression '(1 << -1)' is negative [-fpermissive]
Run Code Online (Sandbox Code Playgroud)
但我认为语义检查应该在废弃的分支上保持不成形.
constexpr但是,通过lambda 进行间接确实有帮助:
template <typename T>
void foo(){
constexpr int x = -1;
constexpr auto p = []() constexpr { return x; }; …Run Code Online (Sandbox Code Playgroud) 我有以下代码:
#include <iostream>
class A;
int main()
{
std::cout << std::is_constructible<A>::value << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
当我使用GCC 8.3时,此代码会编译。但是,当我使用Clang 8.0时,出现编译错误,即不能在类型特征中使用不完整的类型。
哪一个是正确的?是否允许我使用is_constructible不完整的类型(预期值为false),还是不允许我使用?
根据cppreference,std::type_info::operator!=被C ++ 20删除,但是std::type_info::operator==显然仍然存在。
背后的原因是什么?我可能会同意比较不平等是没有意义的,但是然后比较相等也同样是没有意义的,不是吗?
相比之下,必须编写if(!(id1 == id2))并不会使任何代码更清晰if(id1 != id2),相反,相反……