我试图让我的头围绕元组(感谢@litb),他们使用的常见建议是返回> 1值的函数.
这是我通常使用结构的东西,在这种情况下我无法理解元组的优点 - 对于最终的懒惰来说,这似乎是一种容易出错的方法.
借用一个例子,我会用它
struct divide_result {
int quotient;
int remainder;
};
Run Code Online (Sandbox Code Playgroud)
使用元组,你会有
typedef boost::tuple<int, int> divide_result;
Run Code Online (Sandbox Code Playgroud)
但是如果你没有阅读你正在调用的函数的代码(或者评论,如果你足够愚蠢地信任它们),你就不知道哪个int是商,反之亦然.看起来很像......
struct divide_result {
int results[2]; // 0 is quotient, 1 is remainder, I think
};
Run Code Online (Sandbox Code Playgroud)
......这不会让我满怀信心.
那么,什么是元组在该补偿的模糊性结构的优势是什么?
我想知道我可以做什么类型的内省来检测可以通过原始内存副本分配的类型?
例如,据我所知,内置类型的内置类型元组和此类元组的元组将属于此类别.我的动机是,如果可能,我想传输原始字节.
T t1(...); // not necessarely default constructible
T t2(...);
t1 = t2; // should be equivalent to std::memcpy(&t1, &t2, sizeof(T));
// t1 is now an (independent) copy of the value of t2, for example each can go out of scope independently
Run Code Online (Sandbox Code Playgroud)
如果赋值可以(原则上)替换为?,那么在编译类型中可以告诉什么type_trait或组合?type_traitsmemcpy
我想你会为我猜应该fullfil这个条件的类型和让我吃惊的是适合的行为是不是唯一的工作,std::is_trivially_assignable但是std::trivially_destructible.这在某种程度上是有意义的,但我很困惑为什么其他一些选项不能用于预期的情况.
我知道可能没有防弹方法,因为人们总是可以编写一个有效可记忆的类,不能被"检测"为memcopyable,但我正在寻找一个适用于简单直观案例的类.
#include<type_traits>
template<class T> using trait =
std::is_trivially_destructible
// std::is_trivial
// std::is_trivially_copy_assignable
// std::is_trivially_copyable // // std::tuple<double, double> is not trivially copyable!!!
// std::is_trivially_default_constructible
// …Run Code Online (Sandbox Code Playgroud) 使用many如下所示的模板结构,可以返回一组固定的可能不可移动的对象,并使用c ++ 17结构化绑定接收它们(auto [a,b,c] = f();声明变量ab和c并从f返回它们的值,例如结构或元组).
template<typename T1,typename T2,typename T3>
struct many {
T1 a;
T2 b;
T3 c;
};
// guide:
template<class T1, class T2, class T3>
many(T1, T2, T3) -> many<T1, T2, T3>;
auto f(){ return many{string(),5.7, unmovable()}; };
int main(){
auto [x,y,z] = f();
}
Run Code Online (Sandbox Code Playgroud)
正如在这两个问题和答案中所解释的那样(Do std :: tuple和std :: pair是否支持聚合初始化?
特别是ecatmur接受的答案,还有多个返回值(结构化绑定)和不可移动的类型以及C++中保证的RVO 17),std::tuple不支持聚合初始化.这意味着它不能用于保存和返回不可移动的类型.但是一个简单的结构many可以做到这一点,这导致了一个问题:
是否可以创建一个many可以使用任意数量参数的可变版本?
更新:在模板版本中many,是否允许使用以下指南语法?
template<typename Args...>
many(Args...) -> many<Args...>;
Run Code Online (Sandbox Code Playgroud) 重要提示:请参阅这个非常相关的问题:在C++中返回多个值.
我是如何在ANSI C中做同样的事情的?你会使用一个结构或传递函数中的参数的地址吗?我追求极其高效(快速)的代码(时间和空间),即使以可读性为代价.
编辑:谢谢你的所有答案.好吧,我想我有一些解释:我正在写这本书,关于特定领域的某个算法子集.我已经为自己设定了一个非常随意的目标,即以可读性和其他方式为代价,为我的所有算法提供最有效(时间和空间)的实现.这部分是我(一般)问题的本质.
答:我希望我能做到这一点,从(可能)最快到更常见的感觉(所有这些都是先验的,即没有测试):
这有意义吗?如果是这样的话,我认为Jason的回答是最接近的,即使他们都提供了一些"谜题".罗伯特很好,但此时的语义并不是我所追求的(尽管他的建议得到了适当的注意)
谢谢你们.
为什么某些流行语言中的函数只返回一种类型的结果?
即我的意思是为什么编译器给下面的语法错误
public int int returnTwoIntegers(){
.......
........
}
Run Code Online (Sandbox Code Playgroud) 好奇的是,对于java,c,c ++等语言中的方法有多个返回值有任何技术限制,或者仅限于规范?在汇编语言中我理解callee可以弹出一个值来注册.
我已经阅读了一些关于返回多个值的问题,例如在C++和Java中只有一个返回值的原因是什么?,从C++函数和https://softwareengineering.stackexchange.com/questions/203471/why-do-most-programming-languages-only-support-returning-a-single-value-from-af 返回多个值.
我同意用于证明多个返回值不是绝对必要的大多数参数,我理解为什么没有实现这样的功能,但我仍然无法理解为什么我们不能使用多个调用者保存的寄存器例如ECX和EDX返回这样的值.
使用寄存器而不是创建一个Class/Struct来存储这些值或通过引用/指针传递参数不是更快,两者都使用内存来存储它们吗?如果可以做这样的事情,那么任何C/C++编译器是否都使用此功能来加速代码?
编辑:理想的代码是这样的:
(int, int) getTwoValues(void) { return 1, 2; }
int main(int argc, char** argv)
{
(int a, int b) = getTwoValues();//a and b are actually returned in registers so future operations with a and b are faster
//do something with a and b
return 0;
}
Run Code Online (Sandbox Code Playgroud) c++ ×7
c ×3
assembly ×1
boost-tuples ×1
c# ×1
c++11 ×1
c++17 ×1
function ×1
java ×1
memcpy ×1
memory ×1
return ×1
return-value ×1
stack ×1
stack-trace ×1
syntax ×1
templates ×1
tuples ×1
type-traits ×1
x86 ×1