#include <iostream>
int main() {
bool b = true;
std::cout << std::is_same<decltype(!(!b)), bool>::value << "\n";
auto bb = (!(!b));
std::cout << std::is_same<decltype(bb), bool>::value << "\n";
}
Run Code Online (Sandbox Code Playgroud)
上面的代码使用不同的编译器有不同的结果。这是编译器错误还是我遗漏了什么?
最近,我看到这样的说法:
所有指针具有相同的大小是很常见的,但从技术上讲,指针类型具有不同的大小是可能的。
但后来我发现了这样的内容:
虽然指针的大小都是相同的,因为它们只存储内存地址,但我们必须知道它们指向什么类型的东西。
现在,我不确定以上哪种说法是正确的。第二个引用的语句看起来像是来自佛罗里达州立大学计算机科学的 C++ 笔记。
这就是为什么在我看来所有指针都应该具有相同的大小:
1)假设我们有:
int i = 0;
void* ptr = &i;
Run Code Online (Sandbox Code Playgroud)
现在,假设 C++ 标准允许指针具有不同的大小。进一步假设在某些任意机器/编译器上(因为标准允许),a 的void*大小为 2 字节,而 a 的int*大小为 4 字节。
现在,我认为这里有一个问题,即右侧有一个int*大小为 4 字节的 ,而左侧有一个void*大小为 2 字节的 。int*因此,当从到发生隐式转换时,void*将会丢失一些信息。
2)所有指针都保存地址。由于对于给定的机器,所有地址都具有相同的大小,因此所有指针也应该具有相同的大小是非常自然(合乎逻辑的)。
因此,我认为第二句话是正确的。
我的第一个问题是 C++ 标准对此有何规定?
我的第二个问题是,如果 C++ 标准确实允许指针具有不同的大小,那么有理由吗?我的意思是允许指针具有不同的大小对我来说似乎有点不自然(考虑到我上面解释的两点)。所以,我很确定标准委员会一定已经考虑到了这一点(指针可以有不同的大小),并且已经有理由允许指针有不同的大小。请注意,只有当标准确实允许指针具有不同的大小时,我才会问这个(第二个问题)。
c++ pointers void-pointers language-lawyer pointer-conversion
在下面的代码中,在set()a 上调用一个成员函数model,它是一个空指针。这将是未定义的行为。然而,成员函数的参数是另一个函数调用的结果,该函数调用检查是否为model空指针并在这种情况下抛出异常。是否保证estimate()总是在访问之前被调用model,还是仍然是未定义行为(UB)?
#include <iostream>
#include <memory>
#include <vector>
struct Model
{
void set(int x)
{
v.resize(x);
}
std::vector<double> v;
};
int estimate(std::shared_ptr<Model> m)
{
return m ? 3 : throw std::runtime_error("Model is not set");
}
int main()
{
try
{
std::shared_ptr<Model> model; // null pointer here
model->set(estimate(model));
}
catch (const std::runtime_error& e)
{
std::cout << e.what();
}
return 0;
}
Run Code Online (Sandbox Code Playgroud) 我遇到了一个有趣的问题,我无法理解发生了什么:
/* I WANT 6 ELEMENTS */
int lvalue = 6;
std::vector<int*> myvector { 6 }; /* WORKS FINE */
std::vector<int*> myvector{ lvalue }; /* DOESN'T WORK */
/* Element '1': conversion from 'int' to 'const unsigned __int64 requires a narrowing conversion */
Run Code Online (Sandbox Code Playgroud)
据我所知,我提供的单个整数参数可以解释为使用 argument 调用构造函数size_type count,也可以解释为采用初始值设定项列表的构造函数。似乎initialiser_list只有当我提供左值时才调用构造函数,而size_t count当我给出右值int(好吧,至少是一个文字)时才调用构造函数。为什么是这样?
这也意味着:
int num_elements = 6;
std::vector<int> myvector{num_elements};
Run Code Online (Sandbox Code Playgroud)
结果仅是大小为 的向量1;
std::vector<int> myvector(num_elements);
Run Code Online (Sandbox Code Playgroud)
结果是一个 size 的向量num_elements,但我认为应该避免这种初始化,因为偶尔会遇到最令人烦恼的解析问题。
我了解到评估未初始化的变量是未定义的行为。特别int i = i;是未定义的行为。我已阅读未初始化变量用作其自身初始化程序的行为是什么?
但是,使用引用变量来初始化自身也是未定义的行为吗?特别是,int &ref = ref;根据 C++ 标准,UB 也是吗?
int &ref = ref; // Is this well-formed or ill-formed or UB
Run Code Online (Sandbox Code Playgroud)
所有编译器都会编译上述程序(clang 会发出警告)。这是因为它是未定义的行为,所以任何事情都可以发生,还是程序格式良好?
此外,如果我为 分配一些值ref,程序的行为会与之前的情况相比发生变化吗?
int &ref = ref;
int main()
{
ref = 1; //does this change the behavior of the program from previous case
}
Run Code Online (Sandbox Code Playgroud)
我注意到对于第二个片段,我们遇到了段错误。
我读过的一些参考文献是:
在阅读文档时,std::numeric_limits我发现了以下声明:
还提供了所有整数类类型的特化。(自 C++20 起)
我的问题是上面的语句中整数类类型是什么意思。我的意思是,我知道这int是 C++ 中的内置类型。我们可以在C++中提供用户定义的类。但我从未读过有关整数类类型的内容。我尝试在谷歌上搜索该短语,但没有找到与此相关的任何内容。
我正在阅读一篇 SO 帖子,其中一位用户发表了以下评论:
另请注意,
ArrTest<int> ar();使用了最令人烦恼的 parse。
但另一位用户却表示相反:
ArrTest<int> ar();不是“最令人烦恼的解析”。这只是一个函数声明。对于初学者来说这当然很麻烦,但是,正如您链接到的页面所示,“最令人烦恼的解析”更加复杂。
下面给出了该帖子中的代码示例以供参考:
template <class ItemType>
class ArrTest {
public:
ArrTest();
private:
ItemType* info;
};
//some other code here
int main() {
ArrTest<int> ar(); //DOES THIS USE THE MOST VEXING PARSE?
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我的第一个问题是 C++ 标准正式定义的“最令人烦恼的解析”的概念。我的第二个问题是该语句是否ArrTest<int> ar();使用了最令人烦恼的解析。也就是说,上面引用的两条评论哪一条在技术上是正确的?
这似乎也表明这MyObject object();是最令人烦恼的解析。
我正在使用此处列出的书籍学习 C++ 。我特别读到了有关可变参数模板的内容。现在,为了进一步阐明我的概念,我还编写了简单的示例,并尝试使用调试器和 cout 语句自己理解它们。
下面给出了一个用 gcc 编译但被 clang 拒绝的程序。演示。
template<typename T, typename... V>
struct C
{
T v(V()...);;
};
int main()
{
C<int> c; //works with gcc but rejected in clang
C<int, double, int, int> c2; //same here: works with gcc but rejected in clang
}
Run Code Online (Sandbox Code Playgroud)
所以我的问题是哪个编译器就在这里(如果有的话)?
这是 clang 给出的错误:
<source>:6:12: error: '...' must be innermost component of anonymous pack declaration
T v(V()...);;
^~~
...
1 error generated.
Compiler returned: 1
Run Code Online (Sandbox Code Playgroud) 代码如下:
#include <iostream>
#include <type_traits>
class A
{
A() = default;
A(const A&) = default;
A(A&&) = default;
A& operator=(const A&) = default;
A& operator=(A&&) = default;
~A() = default;
int a;
};
int main()
{
std::cout << std::boolalpha <<
std::is_trivially_copy_assignable_v<A> << " " <<
std::is_trivially_copy_constructible_v<A> << " " <<
std::is_trivially_move_assignable_v<A> << " " <<
std::is_trivially_move_constructible_v<A> << " " <<
std::is_trivially_destructible_v<A> << " " <<
std::is_trivially_copyable_v<A> << "\n";
return 0;
}
Run Code Online (Sandbox Code Playgroud)
And the output is false false false false false …
我试图理解为什么在尝试编译此代码时收到警告 -Wsubobject-linkage:
\n基本.hh
\n#pragma once\n\n#include <iostream>\n\ntemplate<char const *s>\nclass Base\n{\npublic:\n void print()\n {\n std::cout << s << std::endl;\n }\n};\nRun Code Online (Sandbox Code Playgroud)\n孩子.hh
\n#pragma once\n\n#include "base.hh"\n\nconstexpr char const hello[] = "Hello world!";\n\nclass Child : public Base<hello>\n{\n};\nRun Code Online (Sandbox Code Playgroud)\n主程序.cc
\n#include "child.hh"\n\nint main(void)\n{\n Child c;\n c.print();\n return 0;\n}\nRun Code Online (Sandbox Code Playgroud)\n跑步时g++ main.cc I get this warning:
In file included from main.cc:1:\nchild.hh:7:7: warning: \xe2\x80\x98Child\xe2\x80\x99 has a base \xe2\x80\x98Base<(& hello)>\xe2\x80\x99 whose type uses the anonymous namespace [-Wsubobject-linkage]\n 7 | class Child : …Run Code Online (Sandbox Code Playgroud)