C在某种程度上并不完全是C++的一个子集.因此,我们可以通过更改名称(stdio.h
to cstdio
,stdlib.h
to cstdlib
)来使用C++中的大多数C函数/头文件.
我的问题实际上是一种语义.在C++代码(使用GCC编译器的最新版本),我可以打电话printf("Hello world!");
,并std::printf("Hello world!");
和它的工作原理完全一样.在我使用它的参考中也显示为std::printf("Hello world!");
.
我的问题是,它是否更适合std::printf();
在C++中使用?有区别吗?
下面这行是什么意思?为什么允许这样做,因为 0 是右值而不是变量名?const
这句话的意义何在?
const int &x = 0;
Run Code Online (Sandbox Code Playgroud) 在尝试理解右值引用的工作原理时,我最终得到了这段代码:
int* iptr = nullptr;
int*&& irr = iptr;
Run Code Online (Sandbox Code Playgroud)
编译上面的代码会出现以下错误:
错误:对'int*'类型的rvalue引用不能绑定到'int*'类型的左值
我理解这是正确的,但为什么下面的代码,我使用a void*
而不是int*
编译绑定,编译没有任何问题?运行时行为是正确的还是我应该期望未定义的行为?
int* iptr = nullptr;
void*&& irr = iptr;
Run Code Online (Sandbox Code Playgroud) 这是一个完整的程序,可以重现我的问题.
#include <vector>
#include <list>
#include <memory>
#include <utility>
int main()
{
std::vector<std::list<std::unique_ptr<int>>> v;
std::list<std::unique_ptr<int>> l;
l.push_back(std::make_unique<int>(0));
l.push_back(std::make_unique<int>(1));
v.push_back(std::move(l)); // error
}
Run Code Online (Sandbox Code Playgroud)
在最后一行,编译器抱怨正在引用delete
d拷贝构造函数std::unique_ptr
.
由于我将列表移动到向量中,因此我假设不会在列表的元素上调用复制构造函数.
为什么会这样?我该怎么办呢?
我正在使用MSVC 2017.
错误的全文:
example.cpp
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/xmemory0(840): error C2280: 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr(const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)': attempting to reference a deleted function
with
[
_Ty=int
]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/memory(1857): note: see declaration of 'std::unique_ptr<int,std::default_delete<_Ty>>::unique_ptr'
with
[
_Ty=int
]
/opt/compiler-explorer/windows/19.10.25017/lib/native/include/xmemory0(959): note: see reference to function template instantiation 'void std::allocator<_Other>::construct<_Objty,const std::unique_ptr<int,std::default_delete<_Ty>>&>(_Objty *,const std::unique_ptr<_Ty,std::default_delete<_Ty>> &)' being compiled …
Run Code Online (Sandbox Code Playgroud) 假设我"C"
在全局范围内具有链接功能.
extern "C" int fun(int);
Run Code Online (Sandbox Code Playgroud)
然后,如果我想让它在命名空间中可见,我会这样做:
namespace foo {
using ::fun;
}
Run Code Online (Sandbox Code Playgroud)
但在此之后,我仍然能够称其为::fun(0)
除 foo::fun(0)
.
所以我的问题是,有没有办法禁止从全局命名空间调用函数fun
,只允许从中调用namespace foo
?
假设我们有一个实现std::aligned_storage
.我为alignof
和alignas
运算符定义了两个宏.
#include <iostream>
#include <cstddef>
#define ALIGNOF(x) alignof(x)
#define ALIGNAS(x) alignas(x)
template<std::size_t N, std::size_t Al = ALIGNOF(std::max_align_t)>
struct aligned_storage
{
struct type {
ALIGNAS(Al) unsigned char data[N];
};
};
int main()
{
// first case
std::cout << ALIGNOF(aligned_storage<16>::type); // Works fine
// second case
std::cout << ALIGNOF(aligned_storage<16, 16>::type); // compiler error
}
Run Code Online (Sandbox Code Playgroud)
在第二种情况下,我在问题的标题中得到错误(用Clang编译,与GCC类似的错误).如果我分别用alignof
和替换宏,则不会出现错误alignas
.为什么是这样?
你开始问我,为什么我这样做之前-原宏有C++ 98兼容的代码,如__alignof
和__attribute__((__aligned__(x)))
,而这些都是具体的编译器,因此宏是我唯一的选择...
编辑: 因此,根据标记为重复的问题,一组额外的括号将解决问题.
std::cout << ALIGNOF((aligned_storage<16, 16>::type)); // compiler error
Run Code Online (Sandbox Code Playgroud)
它没有.那么,我该怎么做呢?(满意的问题?)
是的,我可以使用std::initializer_list
.是的,更简单,我可以进行聚合初始化.但这是如何工作的?我似乎无法克服C++ 17的折叠表达式.那里没有足够的例子.
这是我想出的:
template<class T, std::size_t N>
struct foo
{
T arr[N];
template<typename... Args>
constexpr foo(Args&&... pack)
{
static_assert(sizeof...(pack) <= N, "Too many args");
std::size_t i = 0;
(arr[i++] = ...);
}
};
int main()
{
foo<int, 5> a(1, 2, 3, 4, 5);
}
Run Code Online (Sandbox Code Playgroud)
编辑:与最新的Clang编译.支持折叠表达式.
所以,我的问题很简单:
将默认类构造函数指定为noexcept
或constexpr
(或任何其他可能的东西)是否有任何意义?
struct foo
{
foo() = default;
// vs
constexpr foo() noexcept = default;
// same thing would apply for copy/move ctors and assignment operators
};
Run Code Online (Sandbox Code Playgroud)
两者的行为方式是否相同?
这取决于课程是否为POD?例如,使用上面的示例,两者的行为方式相同,而如果我有一个std::vector<int> v = { 1, 2, 3, 4 };
使用类内赋值的私有成员,则foo() = default;
默认情况下noexcept
不会constexpr
.
通过编写foo() = default;
,编译器只选择最佳版本:noexcept
如果可能,constexpr
如果可能,等等?
请考虑以下代码段:
struct Foo {};
int main()
{
Foo f;
f.~decltype(f)(); // fine with clang, error with gcc
f.~decltype(auto)(); // error with both clang and gcc
}
Run Code Online (Sandbox Code Playgroud)
显式析构函数调用的规则由标准语法处理,pseudo-destructor-name
其定义如下:
pseudo-destructor-name:
nested-name-specifier opt type-name :: ~type-name
nested-name-specifier template simple-template-id :: ~type-name
~type-name
~decltype-specifier
和:
decltype-specifier:
decltype(expression)
decltype(auto)
那么上面的片段不应该按照标准格式良好吗?(不考虑析构函数被调用两次然后第三次调用同一个对象的事实.)
c++ ×9
c++11 ×4
c++14 ×2
c++17 ×2
constants ×1
lvalue ×1
macros ×1
namespaces ×1
reference ×1
std ×1
visual-c++ ×1
zapier ×1
zapier-cli ×1